#include "face.h"
#include "face_common.h"
#include "face_box_struct.h"
#include "sensetime_protocol.h"
#include "face_encrypt.h"

/* debug print interface */
#if defined(FACE_DEBUG)
#define FACE_TASK_DEBUG_LOG(format, ...) OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#define __FACE_TASK_DEBUG_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#else
#define FACE_TASK_DEBUG_LOG(format, ...)
#define __FACE_TASK_DEBUG_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#endif
#define FACE_TASK_LOG(format, ...) OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#define __FACE_TASK_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)

/* virtual hardware interface */
#define VHW_PIN_FACE_POWER vPIN_C7
#define VHW_UART_FACE vUART_3

/* face power control */
#define FACE_MODULE_POWER_ON Device_Write(VHW_PIN_FACE_POWER, NULL, 0, 1)
#define FACE_MODULE_POWER_OFF Device_Write(VHW_PIN_FACE_POWER, NULL, 0, 0)

#define FACE_NV_SIZE sizeof(NvFace_stu_t)

#define MASTER_TO_FACE_MSG_NUM 10						  //主控给人脸的循环消息队列深度
static RingBufferHandle_t rbMasterToFaceMsgHandle = NULL; //主控给人脸的循环消息队列句柄
static RingBufferHandle_t uartFace_rbHandle = NULL;

/*OTA升级子状态处理和切换*/
static FaceOtaStatus_enum_t FaceOtaStatus = OTA_IDLE_STATUS;

static uint16_t id_to_delete = 0;

#pragma pack(1)
typedef struct
{
	uint8_t faceReleaseFlag;			  //人脸经过产测，出厂状态标志 0:未产测    1：产测(已量产)
	uint8_t faceSn[FACE_SN_LEN];		  //人脸模组sn
	uint8_t faceModel[FACE_MODEL_LEN];    //人脸型号
	uint8_t faceVesion[FACE_VERSION_LEN]; //人脸软件版本
	uint16_t face_user_id[MAX_FACE_NUM];
} NvFace_stu_t;

typedef struct
{
	Face_status_enum_t curStatus; //人脸模组当前状态
	Face_mode_enum_t curmode;	  //人脸模组当前的工作模式
	AllowStatus allowBreakIn;	  //当前人脸执行流程    ALLOW:允许打断；    DISALLOW:不允许打断
	uint32_t start_time;		  //起始时间
	uint32_t timeout;			  //超时时间
	FlagStatus busy;			  //当前是否忙状态， SET：忙（只能被终止指令打断，其它事件无法打断）    RESET：可接受外部指令
								  //FlagStatus LowPower;				//电量状态
} Face_Status_stu_t;
#pragma pack()

/*注：这个数据结构数据的排序要和 Face_mode_enum_t 枚举顺序一致*/
static struct
{

	FaceBoxData_stu_t *switchDataBox;
	FaceBoxData_stu_t *informDataBox;
	FaceBoxData_stu_t *dealDataBox;
} faceStatusList[] =
	{
		/*已经休眠断电*/ {&sleepedSwitchBox, &sleepedInformBox, &sleepedDealBox},
		/*正在验证人脸*/ {&vetifyingSwitchBox, &vetifyingInformBox, &vetifyingDealBox},
		/*正在录入人脸*/ {&EnrollingSwitchBox, &EnrollingInformBox, &EnrollingDealBox},
		/*删除人脸*/ {&DeletingSwitchBox, &DeletingInformBox, &DeletingDealBox},
		/*正在升级人脸*/ {&BootingSwitchBox, &BootingInformBox, &BootingDealBox},
		/*执行休眠动作*/ {&sleepingSwitchBox, &sleepingInformBox, &sleepingDealBox},
		/*空闲模式*/ {&idleSwitchBox, &idleInformBox, &idleDealBox},
		/*设置模式*/ {&setingSwitchBox, &setingInformBox, &setingDealBox},
};

static Face_Status_stu_t faceModuleStatus //人脸模组状态
	= {
		.curStatus = SLEEPED_IDLE_STATUS,	 //人脸模组当前状态
		.curmode = FACE_MODULE_SLEEPED_MODE, //人脸模组当前的工作模式
		.allowBreakIn = ALLOW,
		.timeout = FOREVER_TIME_OUT,
		//.LowPower = UNKNOW,
};

static struct
{
	Face_mode_enum_t mode;
	const char *modeName;
} const modeList[] = MODE_LIST;

static struct
{
	Face_event_enum_t event;
	const char *eventName;
} const eventList[] = EVENT_LIST;

static struct
{
	Face_status_enum_t status;
	const char *statusName;
} const statusList[] = STATUS_LIST;

static Master_Face_Msg_stu_t masterFaceMsgBuf; //主控发给人脸任务信息缓存

static s_face_dir faceEnrolledDir = 0; //已经录入的方向

static FlagStatus faceTaskNoFaceFlag = RESET; //未检测到人脸标志  SET：未检测到人脸   RESET：检测到人脸

/*删除的人脸编号*/
static struct
{
	uint16_t userId; //需要删除的人脸ID（存储于人脸模组）
	uint8_t userNum; //人脸用户编号（存储于锁）
} faceDeleteUser;


/**
  * @brief  故障处理
  * @note
  * @param  err：是否故障
  * @return void
  */
static void err_process(uint8_t err)
{
	static uint8_t err_flag = 0xff;
    if (err != err_flag)
    {
        err_flag = err;
        OSAL_MessagePublishErrorCode(ERRCODE_TYPE_FACE, err_flag);
    }
}

/**
  * @brief  发送人脸消息
  * @note   人脸模块产生的动作，通知主任务
  *         
  * @param  FaceActionType_enum_t:事件类型
  * @param  id:用户ID
  */
static void Face_SendActionMsg(FaceActionType_enum_t action, uint8_t id)
{
	FaceMsg_t faceMsg;
	faceMsg.action = action;
	faceMsg.id = id;
	OSAL_MessagePublish(&faceMsg, sizeof(faceMsg));
}

/**
  * @brief  read face release flag
  */
static uint8_t Face_ReadFaceReleaseFlag(void)
{
	uint8_t faceReleaseFlag;
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceReleaseFlag), &faceReleaseFlag, 1);
	return faceReleaseFlag;
}

/**
  * @brief  Write face release flag
  * @note	This flag will be reset every time the program is re-burned 
  *
  * @param  0:not set    1:set
  */
static ErrorStatus Face_SetFaceReleaseFlag(uint8_t flag)
{
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceReleaseFlag), &flag, 1);
}

/**
  * @brief  read face sn
  */
static ErrorStatus Face_ReadFaceSN(uint8_t *pSN)
{
	int i = 0;
	ErrorStatus ret = ERROR;
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceSn), pSN, FACE_SN_LEN);
	for (i = 0; i < FACE_SN_LEN; i++)
	{
		if (!((pSN[i] >= '0' && pSN[i] <= '9') || (pSN[i] >= 'a' && pSN[i] <= 'z') || (pSN[i] >= 'A' && pSN[i] <= 'Z') || (pSN[i] == '-')))
		{
			break;
		}
	}
	if (i >= FACE_SN_LEN - 5) //支持15~20的变长  人脸模组技术支持答复人脸sn长度为17~20个字节
	{
		ret = SUCCESS;
	}
	return ret;
}

/**
  * @brief  write face sn
  */
static ErrorStatus Face_WriteFaceSN(uint8_t *pSN, uint8_t len)
{
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceSn), pSN, FACE_SN_LEN);
}

/**
  * @brief  read face version
  */
static ErrorStatus Face_Read_Version(uint8_t *pData, uint8_t *pLen)
{
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceVesion), pData, FACE_VERSION_LEN);
	uint8_t version_len = strlen(pData);
	for (int i = 1; i < version_len; i++)
	{
		if (!((pData[i] >= '0' && pData[i] <= '9') || pData[i] == '.'))
		{
			return ERROR;
		}
	}
	*pLen = version_len;
	FACE_TASK_LOG("read face version: %s\r\n", pData);
	return SUCCESS;
}

/**
  * @brief  write face version
  */
ErrorStatus Face_WriteFaceVersion(uint8_t *pData)
{
	ErrorStatus status = SUCCESS;
	uint8_t temp[FACE_VERSION_LEN] = {0};
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceVesion), temp, FACE_VERSION_LEN);
	if (strcmp((char *)pData, (char *)&temp) != 0)
	{
		FACE_TASK_LOG("update face version: %s\r\n", pData);
		status = OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceVesion), pData, FACE_VERSION_LEN);
	}
	return status;
}

/**
  * @brief  read face model
  */
static ErrorStatus Face_Read_Model(uint8_t *pData)
{
	ErrorStatus ret = OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceModel), pData, FACE_MODEL_LEN);
	FACE_TASK_LOG("read face model: %s\r\n", pData);
	return ret;
}

/**
  * @brief  write face model
  */
ErrorStatus Face_Write_Model(uint8_t *pData)
{
	ErrorStatus status = SUCCESS;
	uint8_t temp[FACE_MODEL_LEN] = {0};
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceModel), temp, FACE_MODEL_LEN);
	if (strcmp((char *)pData, (char *)&temp) != 0)
	{
		FACE_TASK_LOG("update face model: %s\r\n", pData);
		status = OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceModel), pData, FACE_MODEL_LEN);
	}
	return status;
}

/**
  * @brief  写入人脸内部id
  */
ErrorStatus Face_WriteUserId(uint8_t num, uint8_t *userId)
{
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, userId, 2);
}

/**
  * @brief  读取人脸内部id
  */
ErrorStatus Face_ReadUserId(uint8_t num, uint8_t *userId)
{
	return OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, userId, 2);
}

/**
  * @brief  删除单个人脸索引
  * @param  num : 索引号
  */
ErrorStatus Face_DeleteIndex(uint8_t num)
{
	uint16_t userId = 0xffff;
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, (void *)&userId, 2);
}

/**
  * @brief  删除所有人脸索引数据
  */
ErrorStatus Face_DeleteAllIndex(void)
{
	uint16_t userId[MAX_FACE_NUM];
	memset(userId, 0xff, sizeof(userId));
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, face_user_id), (void *)&userId, sizeof(userId));
}

/**
  * @brief  根据人脸id搜索索引号
  * @param  userId : 人脸ID
  */
int32_t Face_Search_Index(uint8_t *userId)
{
	uint8_t read[2];
	int num = 0;
	for(num = 0; num < MAX_FACE_NUM; num++)
	{
		OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, &read, sizeof(read));
		FACE_TASK_LOG("%d : %x", num, *(uint16_t *)read);
		if(*(uint16_t *)read == *(uint16_t *)userId)
		{
			return num;
		}
	}
	return -1;
}

static uint8_t isTestMode = 0;
static uint8_t Face_IsTestMode(void)
{
	return isTestMode;
}

static void Face_SetTestMode(void)
{
	isTestMode = 1;
}

/**
  * @brief  返回锁当前的时间戳
  *
  * @return 返回UTC时间（以 1970.1.1 00:00:00 为起始时间的秒计数）
  */
static uint32_t Face_GetUtcTimestamp(void)
{
	uint32_t timestamp;
	OSAL_TimeGet(&timestamp, T_UTC);
	return timestamp;
}

/**
  * @brief  当前人脸模组模式
  * @note
  */
static Face_mode_enum_t Face_Get_FaceModule_CurMode(void)
{
	return faceModuleStatus.curmode;
}

/**
  * @brief  当前人脸模组状态
  * @note
  */
static Face_status_enum_t Face_Get_FaceModule_CurStatus(void)
{
	return faceModuleStatus.curStatus;
}

/**
  * @brief  人脸模组上电
  * @note
  */
static void Face_Module_Power_On(void)
{
	FACE_MODULE_POWER_ON;
    Device_Enable(VHW_UART_FACE);
	FaceEncrypt_Set_EnFlag(0); //非加密通信
	Face_SendActionMsg(FACE_ACTION_POWER_ON, 0);
	FACE_TASK_LOG("face module power on\r\n");
}

/**
  * @brief  人脸模组掉电
  * @note
  */
static void Face_Module_Power_Off(void)
{
	FACE_MODULE_POWER_OFF;
    Device_Disable(VHW_UART_FACE);
	Face_SendActionMsg(FACE_ACTION_POWER_OFF, 0);
	FACE_TASK_LOG("face module power off\r\n");
}
/**
  * @brief  人脸任务 人脸模组空闲休眠状态事件处理函数
  *
  * @note
  */
static void Face_SleepedIdle_StatusFun(Face_DealParam_stu_t *param)
{
	Face_Module_Power_Off();
}

/**
  * @brief  人脸模组验证上电状态处理函数
  *
  * @note
  */
static void Face_PoweringOn_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;

	switch (parambuf->event)
	{
	case FACE_POWER_ON_EVEN:
		Face_Module_Power_On();
		break;
	default:
		break;
	}
}

/**
  * @brief  人脸模组初始化加密密钥处理函数
  *
  * @note
  */
static void Face_InitEncryption_Process(void)
{
	uint8_t seeddata[4] = {0};
	uint32_t timedata = 0;
	FaceEncrypt_GenerateRandomNumber(seeddata); //获取随机数
	timedata = Face_GetUtcTimestamp();			//获取时间
	Sensetime_Send_InitEncryption_CMD(seeddata, 4, (uint8_t *)&timedata, 4);
	FaceEncrypt_GenencKey(seeddata); //生成aes密钥
}

/**
  * @brief  人脸模组再次初始化加密密钥处理函数
  *
  * @note 如果第一次加密后，验证sn失败，会再次生成随机码，且第二次生成aes16密码，
  * 	  提高安全性，且这一次的随机密码不往外发
  */
static void Face_Repeat_InitEncryption(uint8_t mode)
{
	if (mode == 2)
	{
		uint8_t seeddata[4] = {0};
		FaceEncrypt_GenerateRandomNumber(seeddata); //获取随机数
		FaceEncrypt_GenencKey(seeddata);			//生成aes密钥
	}
	FaceEncrypt_Set_EnFlag(1);					//启动加密通信
}
/**
  * @brief  人脸模组加密状态状态处理函数
  *
  * @note
  */
static void Face_Encrypting_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	switch (parambuf->event)
	{

	case FACE_MODULE_POWER_ON_READY_EVENT:
		FACE_TASK_LOG("power on,start encrypt\r\n");

		if (Face_IsTestMode())
		{
			Sensetime_Send_DebugEncrytionKeyNum_Cmd((uint8_t *)&faceKeyIndex, FACE_KEY_SIZE);
		}
		else
		{
			if (1 == Face_ReadFaceReleaseFlag()) //已成功发送加密逻辑序列 release 模式
			{
				Face_InitEncryption_Process();
			}
			else
			{
				Sensetime_Send_DebugEncrytionKeyNum_Cmd((uint8_t *)&faceKeyIndex, FACE_KEY_SIZE);
			}
		}
		break;
	case FACE_POWER_ON_INIT_ENCRYPT_EVEN:
		Face_InitEncryption_Process();
		break;
	default:
		break;
	}
}
/**
  * @brief  对比接收的人脸sn和存储的是否一致
  *
  * @note	如果回复出厂设置后首次收到sn，会保存收到的sn码。
  */
static ErrorStatus Face_Comparison_Face_SN(uint8_t *pFaceSn, uint8_t len)
{
	ErrorStatus ret = SUCCESS;
	uint8_t faceModuleSn[FACE_SN_LEN] = {0};
	if (SUCCESS == Face_ReadFaceSN((uint8_t *)&faceModuleSn)) //eeprom中存在人脸sn
	{
		if (0 != memcmp(faceModuleSn, pFaceSn, len))
		{
			FACE_TASK_LOG("Face Sn error");
			ret = ERROR;
		}
	}
	else
	{
		Face_WriteFaceSN(pFaceSn, len); //写入人脸sn
		FACE_TASK_LOG("Face Sn write finish len = %d", len);
	}
	return ret;
}
/**
  * @brief  人脸模组加密完成状态处理函数
  *
  * @note
  */
static void Face_EncrypFinish_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	Face_Encryption_Result_stu_t *pinputdatabuf = (Face_Encryption_Result_stu_t *)parambuf->pinputdata;
	Face_Result_enum_t resultBuf = pinputdatabuf->result;
	FACE_TASK_DEBUG_LOG("FaceTask Encryp fininsh \r\n");
	uint8_t needRepeatInitEncryptionFlag = 0; //需要再次初始化密钥标志  0：不需要再次生成密钥  1：需要再次生成密钥
	switch (parambuf->event)
	{

	case FACE_POWER_ON_ENCRYPT_FINISH_EVEN:
		if (resultBuf == RESULT_SUCCESS_REPORT)
		{
			if (ERROR == Face_Comparison_Face_SN(pinputdatabuf->faceSN, FACE_SN_LEN)) //人脸模块sn比对
			{
				needRepeatInitEncryptionFlag = 2; //sn比对错误，无法使用
			}
		}
		else
		{
			err_process(1);
			needRepeatInitEncryptionFlag = 1;
		}

		break;
	default:
		needRepeatInitEncryptionFlag = 1;
		break;
	}
	if (needRepeatInitEncryptionFlag)
	{
		FACE_TASK_LOG("init encryption fail, repeat, %d\r\n", needRepeatInitEncryptionFlag);
		Face_Repeat_InitEncryption(needRepeatInitEncryptionFlag);
		needRepeatInitEncryptionFlag = 0;
	}
}
/**
  * @brief  人脸验证结果发送给主任务
  *
  * @note
  */
static void Face_Veritying_Send_Msg_To_Master(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;
	switch (result)
	{
	case RESULT_SUCCESS_REPORT:
		action = FACE_ACTION_VERIFY_OK;
		break;
	case RESULT_FAIL_REPORT:
		action = FACE_ACTION_VERIFY_ERR;
		break;

	case RESULT_END:
		action = FACE_ACTION_VERIFY_END;
		break;

	case RESULT_NO_FACE:			   //未检测到人脸
		action = FACE_ACTION_TIME_OUT; //无人脸，以超时结果上报
		break;

	case RUSULT_MODULE_BREAKDOWN:
		action = FACE_ACTION_MODULE_BREAKDOWN;
	default:
		break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_SendActionMsg(action, numbuf);
	}
}

/**
  * @brief  人脸录入结果发送给主任务
  *
  * @note
  */
static void Face_Enrolling_Send_Msg_To_Master(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;
	switch (result)
	{
	case RESULT_SUCCESS_REPORT:
		action = FACE_ACTION_ADD_OK;
		break;
	case RESULT_FAIL_REPORT:
		action = FACE_ACTION_ADD_ERR;
		break;
	case RESULT_FACE_ENROLLED:
		action = FACE_ACTION_ADD_REPEAT;
		break; //人脸已存在
	default:
		break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_SendActionMsg(action, numbuf);
	}
}

/**
  * @brief  人脸删除结果发送给主任务
  *
  * @note
  */
static void Face_Deleting_Send_Msg_To_Master(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;
	switch (result)
	{
	case RESULT_SUCCESS_REPORT:
		action = FACE_ACTION_DEL_OK;
		break;
	case RESULT_FAIL_REPORT:
		action = FACE_ACTION_DEL_FAIL;
		break; //人脸已存在
	case RESULT_NO_FACE:
		action = FACE_ACTION_TIME_OUT;
		break; //无人脸，以超时结果上报
	default:
		break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_SendActionMsg(action, numbuf);
	}
}
/**
  * @brief  人脸升级结果发送给主任务
  *
  * @note
  */
static void Face_Ota_Send_Msg_To_Master(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;
	switch (result)
	{
	case RESULT_SUCCESS_REPORT:
		action = FACE_ACTION_OTA_OK;
		break;
	case RESULT_FAIL_REPORT:
		action = FACE_ACTION_OTA_ERR;
		break; //OTA失败
	default:
		break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_SendActionMsg(action, numbuf);
	}
}

/**
  * @brief  人脸设置结果发送给主任务
  *
  * @note
  */
static void Face_Set_Send_Msg_To_Master(FaceActionType_enum_t action, uint8_t num)
{
	Face_SendActionMsg(action, num);
}
/**
  * @brief  人脸检测标志设置初始值
  *
  * @note  每次启动验证时置位标志为已经检测到人脸
  */
static void Face_No_Face_Init(void)
{
	faceTaskNoFaceFlag = RESET;
}

/**
  * @brief  未检测到人脸标志置位
  *
  * @note
  */
static void Face_No_Face_Check(void *pdata)
{
	Face_NoteFaceStatus_stu_t *pdatabuf = (Face_NoteFaceStatus_stu_t *)pdata;
	/*未检测到人脸标志  SET：未检测到人脸   RESET：检测到人脸*/
	faceTaskNoFaceFlag = (pdatabuf->status == FACE_STATE_NOFACE) ? SET : RESET;
}

/**
  * @brief  判断是否检测到人脸
  *
  * @return SET：未检测到人脸   
  * 		RESET：检测到人脸
  */
static FlagStatus Face_Is_No_Face(void)
{
	/*未检测到人脸标志  SET：未检测到人脸   RESET：检测到人脸*/
	FlagStatus ret = (faceTaskNoFaceFlag == SET) ? SET : RESET;
	return ret;
}

/**
  * @brief  人脸已经录入方向获取
  *
  * @param  
  * 
  * @note
  */
static s_face_dir Face_Enrolled_Direction_Get(void)
{
	return faceEnrolledDir;
}

/**
  * @brief  人脸录入方向选择
  *
  * @param  
  * 
  * @note
  */
static s_face_dir Face_Enroll_Direction_Select(void)
{
	s_face_dir retDir = 0; //需要录入的方向
	s_face_dir EnrolledDir = Face_Enrolled_Direction_Get();
	if ((EnrolledDir & FACE_DIRECTION_MIDDLE) == 0)
	{
		retDir = FACE_DIRECTION_MIDDLE;
	}
	else if ((EnrolledDir & FACE_DIRECTION_RIGHT) == 0)
	{
		retDir = FACE_DIRECTION_RIGHT;
	}
	else if ((EnrolledDir & FACE_DIRECTION_LEFT) == 0)
	{
		retDir = FACE_DIRECTION_LEFT;
	}
	else if ((EnrolledDir & FACE_DIRECTION_DOWN) == 0)
	{
		retDir = FACE_DIRECTION_DOWN;
	}
	else if ((EnrolledDir & FACE_DIRECTION_UP) == 0)
	{
		retDir = FACE_DIRECTION_UP;
	}
	return retDir;
}

/**
  * @brief  人脸录入方向提醒
  *
  * @param  
  * 
  * @note
  */
static void Face_Enroll_Direction_Reminder(s_face_dir dirData)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t num = INVALID_NUM;
	switch (dirData)
	{
	case FACE_DIRECTION_MIDDLE:
		action = FACE_ACTION_ENROLL_MIDDLE_REMINDER;
		break;
	case FACE_DIRECTION_RIGHT:
		action = FACE_ACTION_ENROLL_RIGHT_REMINDER;
		break;
	case FACE_DIRECTION_LEFT:
		action = FACE_ACTION_ENROLL_LEFT_REMINDER;
		break;
	case FACE_DIRECTION_UP:
		action = FACE_ACTION_ENROLL_UP_REMINDER;
		break;
	case FACE_DIRECTION_DOWN:
		action = FACE_ACTION_ENROLL_DOWN_REMINDER;
		break;
	default:
		break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_SendActionMsg(action, num);
	}
}
static FaceActionType_enum_t Face_Single_Enroll_ERR_Dir_Reminder(int16_t yaw, int16_t pitch, int16_t roll)
{
	FaceActionType_enum_t ret = FACE_ACTION_MAX;
	FACE_TASK_LOG("siggle enroll yaw=%#2x,pitch=%#2x, roll=%#2x", yaw, pitch, roll);
	if (yaw > FACE_MIDDLE_MAX)
	{
		ret = FACE_ACTION_LEFT_REMINDER;
	}
	else if (yaw < FACE_MIDDLE_MIN)
	{
		ret = FACE_ACTION_RIGHT_REMINDER;
	}

	else if (pitch > FACE_MIDDLE_MAX)
	{
		ret = FACE_ACTION_UP_REMINDER;
	}
	else if (pitch < FACE_MIDDLE_MIN)
	{
		ret = FACE_ACTION_DOWN_REMINDER;
	}

	else if (roll > FACE_ROLL_MAX //歪头
			 || roll < FACE_ROLL_MIN)
	{
		ret = FACE_ACTION_MIDDLE_REMINDER;
	}
	return ret;
}
/**
  * @brief  录入和验证过程人脸状态提醒
  *
  * @note
  */
static void Face_Verity_Enroll_FaceStatus_Reminder(void *pdata)
{
	uint8_t num = INVALID_NUM;
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	Face_NoteFaceStatus_stu_t *pdatabuf = (Face_NoteFaceStatus_stu_t *)pdata;
	//FACE_TASK_DEBUG_LOG("FaceStatus:state:%#4x,left:%#4x,  top:%#4x,	right:%#4x, bottom:%#4x, yaw:%#4x, pitch:%#4x, roll:%#4x,",\
									pdata->state,pdata->left,pdata->top,	pdata->right,pdata->bottom,pdata->yaw,pdata->pitch,pdata->roll);
	FACE_TASK_DEBUG_LOG("FaceStatus:state:%#4x", pdatabuf->status);
	switch (pdatabuf->status)
	{
	case FACE_STATE_TOOUP: //人脸太靠近图片上边沿
		action = FACE_ACTION_TOOUP;
		break;
	case FACE_STATE_TOODOWN: //人脸太靠近图片下边沿
		action = FACE_ACTION_TOODOWN;
		break;
	case FACE_STATE_TOOLEFT: //人脸太靠近图片左边沿 (模组回复的方向左右是反的)
		action = FACE_ACTION_TOOLRIGHT;
		break;
	case FACE_STATE_TOOLRIGHT: //人脸太考经图片右边沿(模组回复的方向左右是反的)
		action = FACE_ACTION_TOOLEFT;
		break;
	case FACE_STATE_FAR: //人脸距离太远
		action = FACE_ACTION_FAR;
		break;
	case FACE_STATE_CLOSE: //人脸距离太近
		action = FACE_ACTION_CLOSE;
		break;
	case FACE_STATE_EYEBROW_OCCLUSION: //眉毛遮挡
		action = FACE_ACTION_EYEBROW_OCCLUSION;
		break;
	case FACE_STATE_EYE_OCCLUSION: //眼睛遮挡
		action = FACE_ACTION_EYE_OCCLUSION;
		break;
	case FACE_STATE_FACE_OCCLUSION: //脸部遮挡
		action = FACE_ACTION_FACE_OCCLUSION;
		break;
	case FACE_STATE_NOFACE:
		action = FACE_ACTION_NOFACE;
		break;
	case FACE_STATE_DIRECTION_ERROR: //录入人脸方向错误
#if defined(FACE_ENROLL_SINGLE)		 //单帧录入
		action = Face_Single_Enroll_ERR_Dir_Reminder(pdatabuf->yaw, pdatabuf->pitch, pdatabuf->roll);
		action = (action == FACE_ACTION_MAX) ? FACE_ACTION_DIRECTION_ERROR : action;
#else //多帧录入
		count++;
		if (count % 2 == 0)
		{
			needEnrollDir = Face_Enroll_Direction_Select();
			Face_Enroll_Direction_Reminder(needEnrollDir);
		}
		else
		{
			action = FACE_ACTION_DIRECTION_ERROR;
		}
#endif
		break;

	default:
		break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_SendActionMsg(action, num);
	}
}
/**
  * @brief  人脸模组验证执行状态处理函数
  *
  * @note
  */
static void Face_VerityingExcuteOrder_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();

	FACE_TASK_DEBUG_LOG("Veritying\r\n");
	switch (parambuf->event)
	{
	case FACE_MASTER_START_VERITY_EVENT:
		FACE_TASK_LOG("start verity \r\n");
		Master_Face_Msg_stu_t *pinputdatabuf = (Master_Face_Msg_stu_t *)param->pinputdata;
		Sensetime_Send_StartVerity_CMD(pinputdatabuf->del_mode);
		startTime = OSAL_GetTickCount();
		Face_No_Face_Init();
		break;
	case FACE_NID_FACE_STATUS_EVENT: //录入和验证人脸状态信息返回:人脸状态信息返回
		Face_No_Face_Check(parambuf->pinputdata);
		if (OSAL_PastTime(currentTime, startTime) > (FACE_REMINDER_INTERVAL)) //间隔时间提醒
		{
			startTime = OSAL_GetTickCount();
			Face_Verity_Enroll_FaceStatus_Reminder(parambuf->pinputdata);
		}
		break;
	default:
		break;
	}
}

/**
  * @brief  人脸模组验证完成状态处理函数
  *
  * @note
  */
static void Face_VerityingFinished_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	Face_VerityResult_stu_t *pinputdatabuf = parambuf->pinputdata;
	Face_Result_enum_t resultBuf = pinputdatabuf->result;
	//FaceActionType_enum_t actionBuf;
	FACE_TASK_DEBUG_LOG("Verity Finish\r\n");
	switch (parambuf->event)
	{
	case FACE_VERITY_SUCCESS_FINISHED_EVENT: //人脸验证结束
		FACE_TASK_LOG("Send verity result = %d num = %d\r\n", resultBuf, pinputdatabuf->usernum);
		Face_Veritying_Send_Msg_To_Master(resultBuf, pinputdatabuf->usernum);
		break;
	case FACE_VERITY_FAIL_FINISHED_EVENT:
	case FACE_TIMEOUT_ENENT:
		resultBuf = ((resultBuf != RESULT_VERIFY_FAIL_REPORT) && SET == Face_Is_No_Face()) ? RESULT_NO_FACE : RESULT_FAIL_REPORT;	
		FACE_TASK_LOG("Send verity result = %d \r\n", resultBuf);
		Face_Veritying_Send_Msg_To_Master(resultBuf, INVALID_NUM);
		break;
	default:
		break;
	}
}

/**
  * @brief  人脸模组发送休眠指令状态处理函数
  *
  * @note
  */
static void Face_SleepingSending_StatusFun(Face_DealParam_stu_t *param)
{
	FACE_TASK_LOG("Sending PowerDowm\r\n");
	Sensetime_Send_PowerDowm_CMD(); //发送休眠指令
}

/**
  * @brief  人脸任务 人脸模组空闲状态事件处理函数
  *
  * @note
  */
static void Face_IdleSending_StatusFun(Face_DealParam_stu_t *param)
{
	FACE_TASK_DEBUG_LOG("Idle Sending");
	Sensetime_Send_Reset_CMD(); //发送终止当前操作指令（验证、注册）
}

/**
  * @brief  人脸已经录入方向设置
  *
  * @param  dir 已录入方向
  * 
  * @note
  */
static void Face_Enrolled_Direction_Set(s_face_dir dir)
{
	faceEnrolledDir = dir;
}

/**
  * @brief  人脸模组录入执行状态处理函数
  *
  * @note
  */
static void Face_EnrollingExcuteOrder_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();
	s_face_dir needEnrollDir;
	FACE_TASK_DEBUG_LOG("Enrolling");
	switch (parambuf->event)
	{
	case FACE_MASTER_START_ENROLL_EVENT:
	{
		Master_Face_Msg_stu_t *pinputdatabuf = (Master_Face_Msg_stu_t *)param->pinputdata;
		masterFaceMsgBuf = *pinputdatabuf;
	}
		//case FACE_MODULE_POWER_ON_READY_EVENT:         //人脸模组上电完成
		FACE_TASK_LOG("start enroll\r\n");
		Face_Enrolled_Direction_Set(0);											  //已经录入方向清零
		needEnrollDir = Face_Enroll_Direction_Select();							  //人脸录入方向选择
		Face_Enroll_Direction_Reminder(needEnrollDir);							  //人脸录入方向提醒
		// Sensetime_Send_FaceReset_CMD();											  //发送清除录入记录给模组
		Sensetime_Send_StartEnroll_CMD(masterFaceMsgBuf.startNum, needEnrollDir); //启动指定方向人脸的录入
		startTime = OSAL_GetTickCount();
		break;

	case FACE_NID_FACE_STATUS_EVENT: //录入和验证人脸状态信息返回:人脸状态信息返回
	{
		if (OSAL_PastTime(currentTime, startTime) > FACE_REMINDER_INTERVAL) //间隔时间提醒
		{
			startTime = OSAL_GetTickCount();
			Face_Verity_Enroll_FaceStatus_Reminder(parambuf->pinputdata);
		}
	}
	break;

	case FACE_ENROLL_ENROLL_NEXT_DIR_EVENT: //人脸录入下一方向人脸
	{
		Face_EnrollResult_stu_t *pinputdatabuf = parambuf->pinputdata;
		FACE_TASK_LOG("Enrolling next face  result = %#2x,enrolledDir = %#2x", pinputdatabuf->result, pinputdatabuf->enrolledFaceDir);
		Face_Enrolled_Direction_Set(pinputdatabuf->enrolledFaceDir); //已经录入的方向
		needEnrollDir = Face_Enroll_Direction_Select();
		Face_Enroll_Direction_Reminder(needEnrollDir);
		Sensetime_Send_StartEnroll_CMD(masterFaceMsgBuf.startNum, needEnrollDir);
		startTime = OSAL_GetTickCount();
		break;
	}
	default:
		break;
	}
}

/**
  * @brief  人脸模组录入完成状态处理函数
  *
  * @note
  */
static void Face_EnrollingFinished_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	Face_EnrollResult_stu_t *pinputdatabuf = parambuf->pinputdata;
	Face_Result_enum_t resultBuf = pinputdatabuf->result;
	uint8_t num = masterFaceMsgBuf.startNum;

    #if 0
	uint8_t faceVersion[FACE_VERSION_LEN] = {0};
	uint8_t len = 0;
	uint32_t version = 0;
    #endif
    
	FACE_TASK_DEBUG_LOG("Enroll Finished");
	switch (parambuf->event)
	{
	case FACE_ENROLL_FINISHED_EVENT: //人脸录入结束
	#if 0
		if (Face_Read_Version(faceVersion, &len) == SUCCESS)
		{
			FACE_TASK_LOG("faceVersion : %s", faceVersion);
			version = (faceVersion[1] - '0') * 10000 + (faceVersion[3] - '0') * 1000 + (faceVersion[5] - '0') * 100 + (faceVersion[6] - '0') * 10 + (faceVersion[7] - '0');
			if (version < 20005)
			{
				FACE_TASK_LOG("Set MID_SET_THRESHOLD_LEVEL\r\n");
				Sensetime_Send_SetThresholdLevel_Cmd(4, 2);
			}
			else
			{
				Sensetime_Send_SetThresholdLevel_Cmd(2, 2);
				FACE_TASK_LOG("version >= V2.0.005");
			}
		}
		else
		{
			FACE_TASK_LOG("read version fail");
		}
	#endif
		FACE_TASK_LOG("Send enroll result = %d num = %d\r\n", resultBuf, num);

		/* 存储userid */
		Face_WriteUserId(num, (uint8_t *)&pinputdatabuf->user_id);

		Face_Enrolling_Send_Msg_To_Master(resultBuf, num);
		break;

	case FACE_TIMEOUT_ENENT:
		resultBuf = RESULT_FAIL_REPORT;
		FACE_TASK_LOG("Send reroll result = %d \r\n", resultBuf);
		Face_Enrolling_Send_Msg_To_Master(resultBuf, num);
		break;

	default:
		break;
	}
}

/**
  * @brief  人脸模组删除开始事件处理
  *
  * @note
  */
static void Face_Start_Delet_Event_Process(uint8_t startNum, uint8_t endNum)
{
	if (FACE_DELETE_ALL_NUN == endNum) //删除全部人脸
	{
		faceDeleteUser.userId = FACE_DELETE_ALL_NUN | (FACE_DELETE_ALL_NUN < 8);
		faceDeleteUser.userNum = FACE_DELETE_ALL_NUN;
		Sensetime_Send_Start_DelAll_CMD(); //发送删除全部人脸的消息给人脸模组
	}
	else
	{
#if 1 //根据编号删除
		faceDeleteUser.userId = id_to_delete;
		faceDeleteUser.userNum = startNum;
		Sensetime_Send_Start_DelUser_CMD(faceDeleteUser.userId);
#else
		Sensetime_Send_StartVerity_CMD(2); //删除单个人脸，先识别当前人脸，再删除验证成功的编号
#endif
	}
}

/**
  * @brief  人脸模组删除执行状态处理函数
  *
  * @note
  */
static void Face_DeletingExcuteOrder_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;

	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();
	FACE_TASK_DEBUG_LOG("Deleting\r\n");
	switch (parambuf->event)
	{
	case FACE_MASTER_START_DELETE_EVENT: //主任务启动人脸删除：启动删除
	{
		Master_Face_Msg_stu_t *pinputdatabuf = (Master_Face_Msg_stu_t *)param->pinputdata;
		masterFaceMsgBuf = *pinputdatabuf;
	}
		//case FACE_MODULE_POWER_ON_READY_EVENT:         //人脸模组上电完成
		FACE_TASK_LOG("start delete \r\n");
		Face_Start_Delet_Event_Process(masterFaceMsgBuf.startNum, masterFaceMsgBuf.endNum);
		startTime = OSAL_GetTickCount();
		Face_No_Face_Init();
		break;

	case FACE_NID_FACE_STATUS_EVENT: //录入和验证人脸状态信息返回:人脸状态信息返回
	{
		Face_No_Face_Check(parambuf->pinputdata);
		if (OSAL_PastTime(currentTime, startTime) > FACE_REMINDER_INTERVAL) //间隔时间提醒
		{
			startTime = OSAL_GetTickCount();
			Face_Verity_Enroll_FaceStatus_Reminder(parambuf->pinputdata);
		}
	}
	break;

	case FACE_VERITY_SUCCESS_FINISHED_EVENT: //人脸验证完成
	{
		Face_VerityResult_stu_t *pinputdatabuf = parambuf->pinputdata;
		if (pinputdatabuf->result == RESULT_SUCCESS_REPORT) //验证成功
		{
			faceDeleteUser.userId = (pinputdatabuf->user_id_heb << 8) | (pinputdatabuf->user_id_leb);
			faceDeleteUser.userNum = pinputdatabuf->usernum;
			Sensetime_Send_Start_DelUser_CMD(faceDeleteUser.userId);
		}
	}
	break;

	default:
		break;
	}
}

/**
  * @brief  人脸模组删除完成状态处理函数
  *
  * @note
  */
static void Face_deletingFinished_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	Face_DeleteResult_stu_t *pinputdatabuf = parambuf->pinputdata;
	Face_Result_enum_t resultBuf = pinputdatabuf->result;
	uint8_t num = faceDeleteUser.userNum;
	FACE_TASK_DEBUG_LOG("delet Finished");
	switch (parambuf->event)
	{
	case FACE_DELETE_FINISH_EVENT: //人脸删除结束
		FACE_TASK_LOG("Send delete result = %d num = %d\r\n", resultBuf, num);
		Face_Deleting_Send_Msg_To_Master(resultBuf, num);
		break;

	case FACE_VERITY_FAIL_FINISHED_EVENT: //单个删除人脸识别失败
	case FACE_TIMEOUT_ENENT:
		resultBuf = (SET == Face_Is_No_Face()) ? RESULT_NO_FACE : RESULT_FAIL_REPORT;
		FACE_TASK_LOG("Send delete result = %d \r\n", resultBuf);
		Face_Deleting_Send_Msg_To_Master(resultBuf, num);
		break;

	default:
		break;
	}
}
static void Face_Set_Start_Process(Face_Msg_Id_enum_t msgId, Master_Msg_Cb_fun_t cb)
{
	Face_Msg_Id_enum_t msgIdbuf = msgId;
	switch (msgIdbuf)
	{
	case SET_MSGID_SET_DEMO_MODE:
		Sensetime_Send_SetDemoMode_CMD(0x01);
		break;

	case SET_MSGID_SET_WORK_MODE:
		Sensetime_Send_SetDemoMode_CMD(0x00);
		break;

	case SET_MSGID_GET_VERSION:
		Sensetime_Send_Get_Version_CMD(cb);
		break;

	case SET_MSGID_SET_RELEASE_ENC:
		Sensetime_Send_ReleaseEncrytionKeyNum_Cmd((uint8_t *)&faceKeyIndex, FACE_KEY_SIZE);
		break;
	default:
		break;
	}
}
/**
  * @brief  人脸模组设置执行状态处理函数
  *
  * @note
  */
static void Face_SetingExcuteOrder_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	uint32_t currentTime = OSAL_GetTickCount();

	FACE_TASK_DEBUG_LOG("Seting\r\n");
	switch (parambuf->event)
	{
	case FACE_START_SET_EVENT: //人脸设置模式开始
		Face_Set_Start_Process(parambuf->resultId, parambuf->cb);
		break;

	default:
		break;
	}
}
/**
  * @brief  人脸模组设置加密密钥处理函数
  *
  * @note
  */
static void Face_Set_Release_Enc_Process(Face_Msg_Id_enum_t msgId, Face_Result_enum_t result, void *pinputdata)
{
	if (result == RESULT_SUCCESS_REPORT)
	{
		Face_SetFaceReleaseFlag(1);
		Face_Set_Send_Msg_To_Master(FACE_ACTION_ENC_SUCCESS, INVALID_NUM);
	}
	else if (result == RESULT_ENCRYPTED)
	{
		Face_SetFaceReleaseFlag(1);
		Face_Set_Send_Msg_To_Master(FACE_ACTION_ENCRYPTED, INVALID_NUM);
	}
	else
	{
		Face_SetFaceReleaseFlag(0);
		Face_Set_Send_Msg_To_Master(FACE_ACTION_ENC_FAIL, INVALID_NUM);
	}
}
/**
  * @brief  人脸模组设置完成处理函数
  *
  * @note
  */
static void Face_Set_Finish_Process(Face_Msg_Id_enum_t msgId, Face_Result_enum_t result, void *pinputdata)
{
	Face_Msg_Id_enum_t msgIdbuf = msgId;
	switch (msgIdbuf)
	{
	case SET_MSGID_SET_RELEASE_ENC: //设定量产加密秘钥序列
		Face_Set_Release_Enc_Process(msgId, result, pinputdata);
		break;
	default:
		break;
	}
}
/**
  * @brief  人脸模组设置完成状态处理函数
  *
  * @note
  */
static void Face_SetingFinished_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	Face_VerityResult_stu_t *pinputdatabuf = parambuf->pinputdata;
	Face_Result_enum_t resultBuf = pinputdatabuf->result;
	//FaceActionType_enum_t actionBuf;
	FACE_TASK_DEBUG_LOG("Set Finished\r\n");
	switch (parambuf->event)
	{
	case FACE_SET_FINISH_EVENT: //人脸设置结束
		Face_Set_Finish_Process(parambuf->resultId, resultBuf, parambuf->pinputdata);
		break;
	case FACE_TIMEOUT_ENENT:
		FACE_TASK_DEBUG_LOG("Set Finished Time Out\r\n");
		break;
	default:
		break;
	}
}

/**
  * @brief  设置人脸模组升级状态
  *
  * @note
  */
static void Face_FaceOtaStatus_Set(FaceOtaStatus_enum_t status)
{
	FaceOtaStatus = status;
	FACE_TASK_LOG("FaceOtaStatus : %d\r\n", FaceOtaStatus);
	if (FaceOtaStatus == OTA_IDLE_STATUS)
	{
		OSAL_SetTaskStatus(TASK_STA_NORMAL);
	}
	else
	{
		OSAL_SetTaskStatus(TASK_STA_ACTIVE);
	}
}

/**
  * @brief  获取人脸模组升级状态
  *
  * @note
  */
static FaceOtaStatus_enum_t Face_FaceOtaStatus_Get(void)
{
	return FaceOtaStatus;
}

/**
  * @brief  人脸模组升级发送获取固件信息状态处理函数
  *
  * @note
  */
static ErrorStatus Face_Sending_Start_OTA(Face_OtaParam_stu_t *param)
{
	FACE_TASK_LOG("send start ota");
	Sensetime_Send_StartOta_CMD(); //发送启动升级的消息给人脸模组
	return SUCCESS;
}

/**
  * @brief  人脸模组升级前期处理函数
  *
  * @note
  */
static void Face_FaceOtaPrepareStatus_Process(Face_OtaParam_stu_t *param)
{
	FaceOtaStatus_enum_t statusbuf = Face_FaceOtaStatus_Get();
	ErrorStatus retbuf = ERROR;
	uint8_t len = faceOtaBoxData.len;
	FaceOtaDealSwitch_stu_t *pOtaBoxDataBuf = (FaceOtaDealSwitch_stu_t *)faceOtaBoxData.pOtaBoxData;
	uint8_t i;
	for (i = 0; i < len; i++)
	{
		if (statusbuf == pOtaBoxDataBuf[i].curOtaStatus)
		{
			FACE_TASK_LOG("face ota pre status %2d", statusbuf);
			retbuf = pOtaBoxDataBuf[i].pFuntion(param); //执行对应状态的函数
			break;
		}
	}
	if (retbuf == SUCCESS)
	{
		Face_FaceOtaStatus_Set(pOtaBoxDataBuf[i].nextOtaStatus); //更新状态
	}
}

/**
  * @brief  OTA结束，1s后进入休眠
  *
  * @note
  */
static ErrorStatus Face_Get_Version(Master_Msg_Cb_fun_t cb);
static void Face_OTA_Finish(void)
{
	uint8_t faceVersion[FACE_VERSION_LEN] = {0};
	FACE_TASK_LOG("ota end\r\n");
	Face_FaceOtaStatus_Set(OTA_IDLE_STATUS);
	Face_WriteFaceVersion(faceVersion); //清除人脸软件版本
	Face_Get_Version(NULL); //重新获取软件版本号
}
/**
  * @brief  人脸模组OTA
  *
  * @note
  */
static void Face_OTA_ExcuteOrder_StatusFun(Face_DealParam_stu_t *param)
{
	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();

	Face_DealParam_stu_t *parambuf = param;
	Face_OtaParam_stu_t otaParambuf = {
		.resultId = parambuf->resultId,
		.pdata = parambuf->pinputdata,
	};
	//Face_Ota_Result_stu_t *pinputdatabuf = parambuf->pinputdata;
	FACE_TASK_DEBUG_LOG("OTAING");
	switch (parambuf->event)
	{
	case FACE_MASTER_START_OTA_EVEN: //启动OTA
	{
		FACE_TASK_LOG("start ota\r\n");
		Face_FaceOtaStatus_Set(OTA_IDLE_STATUS);
		otaParambuf.resultId = OTA_MSGID_RECEIVE_START_OTA_EVEN;
		Face_FaceOtaPrepareStatus_Process(&otaParambuf);
		break;
	}

	case FACE_OTA_PREPAREING_EVEN: //OTA 前期准备
		Face_SendActionMsg(FACE_ACTION_ENTER_OTA_MODE, 0x00);
		Face_FaceOtaPrepareStatus_Process(&otaParambuf);
		break;

	case FACE_OTA_KEEP_SENDING_PACKET_EVEN: //OTA正在发送升级包
	{
		Face_OtaSendFirmware_Result_stu_t *pinputdatabuf = parambuf->pinputdata;
		Face_Result_enum_t resultBuf = pinputdatabuf->result;
		if (resultBuf == RUSULT_OTA_SENDING_FIRMWARE)
		{
			FACE_TASK_LOG("ota sending firmware\r\n");
			startTime = OSAL_GetTickCount();
		}
		else
		{
			FACE_TASK_LOG("ota no sending firmware\r\n");
			if (OSAL_PastTime(currentTime, startTime) > FACE_OTA_EXCUTING_TIMEOUT) //判断是否超时
			{
				Face_OTA_Finish(); //长时间没有串口数据交换表示ota结束
			}
		}
	}
	break;

	default:
		break;
	}
}

static void Face_OtaFinish_Process(Face_Result_enum_t result)
{
	switch (result)
	{
	case RESULT_SUCCESS_REPORT:
		Face_Ota_Send_Msg_To_Master(RESULT_SUCCESS_REPORT, INVALID_NUM);
		break;

	case RESULT_FAIL_REPORT:
		Face_Ota_Send_Msg_To_Master(RESULT_FAIL_REPORT, INVALID_NUM);
		break;
	}
}
/**
  * @brief  人脸模组OTA结束
  *
  * @note
  */
static void Face_OtaFinished_StatusFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	Face_Ota_Result_stu_t *pinputdatabuf = parambuf->pinputdata;
	Face_Result_enum_t resultBuf = pinputdatabuf->result;
	FACE_TASK_DEBUG_LOG("Ota Finished");
	switch (parambuf->event)
	{
	case FACE_OTA_FINISH_EVEN: //人脸升级结束
		Face_OtaFinish_Process(resultBuf);
		Face_OTA_Finish();
		break;

	case FACE_TIMEOUT_ENENT: //超时
		Face_Ota_Send_Msg_To_Master(RESULT_FAIL_REPORT, INVALID_NUM);
		Face_OTA_Finish();
		break;
	default:
		break;
	}
}
/**
  * @brief  人脸任务 人脸模组状态切换
  *
  * @note
  */
static void Face_Switch_Status(FaceBoxData_stu_t boxinformData, Face_mode_enum_t mode, Face_status_enum_t status, Face_Status_stu_t *pFaceModuleStatus)
{
	FaceInform_stu_t *informData = (FaceInform_stu_t *)boxinformData.pBoxData;
	uint8_t len = boxinformData.len;
	//Face_mode_enum_t curModeBuf = boxinformData.mode;
	Face_status_enum_t curStatusBuf = status;
	for (int i = 0; i < len; i++)
	{
		if (informData[i].status == curStatusBuf)
		{
			pFaceModuleStatus->curStatus = informData[i].status;
			pFaceModuleStatus->curmode = mode;
			pFaceModuleStatus->allowBreakIn = informData[i].allowBreakIn;
			pFaceModuleStatus->start_time = OSAL_GetTickCount();
			pFaceModuleStatus->timeout = informData[i].timeout;
			pFaceModuleStatus->busy = informData[i].busy;
		}
	}
}

/**
  * @brief  查找对应模式和状态的处理函数
  *
  * @param	boxDealData	要查找的模式对应处理框
  * @param	status		要查找的状态
  * 
  * @note
  */

static FaceTackFunction_fun_t Face_Find_Deal_Function(FaceBoxData_stu_t boxDealData, Face_status_enum_t status)
{
	FaceTackFunction_fun_t retfun = NULL;
	FaceDeal_stu_t *deal = (FaceDeal_stu_t *)boxDealData.pBoxData;
	uint8_t len = boxDealData.len;
	for (int i = 0; i < len; i++)
	{
		if (deal[i].Status == status)
		{
			retfun = deal[i].pFuntion;
			break;
		}
	}
	return retfun;
}

/**
  * @brief  查找下一状态和模式
  *
  * @note
  */
static ErrorStatus Face_Find_NextStatus_NextMode(FaceBoxData_stu_t boxSwitchData, Face_status_enum_t curStatus, Face_event_enum_t event,
												 Face_status_enum_t *nextStatus, Face_mode_enum_t *nextMode)
{
	ErrorStatus ret = ERROR;
	FaceSwitch_stu_t *switchData = (FaceSwitch_stu_t *)boxSwitchData.pBoxData;
	uint8_t len = boxSwitchData.len;

	for (int i = 0; i < len; i++)
	{
		if ((switchData[i].curStatus == EVENT_SWITCH_ANY_STATUS) //无视当前状态，只要事件发生,立即切换状态和模式
			|| (switchData[i].curStatus == curStatus))			 //查找多对应状态
		{
			if (switchData[i].event == event)
			{
				*nextMode = switchData[i].nextMode;
				*nextStatus = switchData[i].nextStatus;
				ret = SUCCESS;
				break;
			}
		}
	}
	return ret;
}

static void Face_Print_Mode(Face_mode_enum_t mode)
{
	uint8_t i;
	uint8_t len = OSAL_LENGTH(modeList);

	for (i = 0; i < len; i++)
	{
		if (modeList[i].mode == mode)
		{
			FACE_TASK_DEBUG_LOG("%s,\r\n", modeList[i].modeName);
			break;
		}
	}
	if (i == len)
	{
		FACE_TASK_DEBUG_LOG("mode default,\r\n");
	}
}

static void Face_Print_Status(Face_status_enum_t status)
{
	uint8_t i;
	uint8_t len = OSAL_LENGTH(statusList);

	for (i = 0; i < len; i++)
	{
		if (statusList[i].status == status)
		{
			FACE_TASK_DEBUG_LOG("%s,\r\n", statusList[i].statusName);
			break;
		}
	}
	if (i == len)
	{
		FACE_TASK_DEBUG_LOG("status default,\r\n");
	}
}

static void Face_Print_Event(Face_event_enum_t event)
{
	uint8_t i;
	uint8_t len = OSAL_LENGTH(eventList);

	for (i = 0; i < len; i++)
	{
		if (eventList[i].event == event)
		{
			FACE_TASK_DEBUG_LOG("%s,\r\n", eventList[i].eventName);
			break;
		}
	}
	if (i == len)
	{
		FACE_TASK_DEBUG_LOG("event default,\r\n");
	}
}

static void Face_Print_Mode_Status_Event(FlagStatus flag, Face_mode_enum_t mode, Face_status_enum_t status, Face_event_enum_t event)
{
	FACE_TASK_DEBUG_LOG("\r\n\r\n\r\n");
	if (flag == RESET)
	{
		FACE_TASK_DEBUG_LOG("Even_Deal Current:");
	}
	else
	{
		FACE_TASK_DEBUG_LOG("Even_Deal New:");
	}
	Face_Print_Mode(mode);
	Face_Print_Status(status);
	Face_Print_Event(event);
	FACE_TASK_DEBUG_LOG("\r\n\r\n\r\n");
}

/**
  * @brief  验证模式切换为其它模式，告知红外模块验证结束
  *
  * @note
  */
static void Face_Verity_Mode_End_Check_Process(Face_mode_enum_t curMode, Face_mode_enum_t nextMode)
{
	if ((curMode == FACE_MODULE_VERITYFYING_MODE) && (curMode != nextMode))
	{
		Face_Veritying_Send_Msg_To_Master(RESULT_END, INVALID_NUM);
	}
}

/**
  * @brief  人脸模组故障判断和处理
  *
  * @note 连续六次模组上电都超时，则表示模组异常
  */
static void Face_Module_Breakdown_Check_Process(Face_status_enum_t curStatus, Face_event_enum_t curEvent)
{
	static uint8_t modulePowerOnTimeoutCount = 0; //模块上电超时计数
	if (curStatus != POWERING_ON_STATUS)
		return;
	if (curEvent == FACE_TIMEOUT_ENENT)
	{
		if (modulePowerOnTimeoutCount < 6)
		{
			modulePowerOnTimeoutCount++;
		}
		else
		{
			Face_Veritying_Send_Msg_To_Master(RUSULT_MODULE_BREAKDOWN, INVALID_NUM);
		}
	}
	else
	{
		modulePowerOnTimeoutCount = 0;
	}
}
/**
  * @brief  人脸任务 人脸模组事件处理
  *
  * @note
  */

void Face_Module_Even_Deal(Face_DealParam_stu_t *param)
{
	Face_status_enum_t curStatusBuf = faceModuleStatus.curStatus;					//当前状态缓存
	Face_mode_enum_t curModeBuf = faceModuleStatus.curmode;							//当前模式缓存
	Face_status_enum_t NextStatusBuf = curStatusBuf;								//下一状态缓存
	Face_mode_enum_t NextModeBuf = curModeBuf;										//下一模式缓存
	Face_event_enum_t curEventbuf = param->event;									//当前事件缓存
	FaceBoxData_stu_t *dealDataBoxBuf = NULL;										//模式对应的处理框
	FaceBoxData_stu_t *switchDataBoxBuf = faceStatusList[curModeBuf].switchDataBox; //当前模式对应的状态切换框
	FaceBoxData_stu_t *informDataBoxBuf;
	FaceTackFunction_fun_t pFun = NULL;
	ErrorStatus ret;

	if (FACE_NID_FACE_STATUS_EVENT != curEventbuf)
	{
		FACE_TASK_LOG("Even_Deal curMode=%#2x, curStatus=%#2x, event=%#2x\r\n", curModeBuf, curStatusBuf, curEventbuf);
		Face_Print_Mode_Status_Event(RESET, curModeBuf, curStatusBuf, curEventbuf);
	}

	ret = Face_Find_NextStatus_NextMode(*switchDataBoxBuf, curStatusBuf, curEventbuf, &NextStatusBuf, &NextModeBuf);

	if (FACE_NID_FACE_STATUS_EVENT != curEventbuf)
	{
		FACE_TASK_LOG("Even_Deal newMode=%#2x,  newStatus=%#2x, event=%#2x\r\n", NextModeBuf, NextStatusBuf, curEventbuf);
		Face_Print_Mode_Status_Event(SET, NextModeBuf, NextStatusBuf, curEventbuf);
	}
	if (ret == SUCCESS) //切换框中查找到对应的状态和事件
	{
		Face_Verity_Mode_End_Check_Process(curModeBuf, NextModeBuf);
		Face_Module_Breakdown_Check_Process(curStatusBuf, curEventbuf);
		FACE_TASK_DEBUG_LOG("face task find next mode success");
		informDataBoxBuf = faceStatusList[NextModeBuf].informDataBox;
		Face_Switch_Status(*informDataBoxBuf, NextModeBuf, NextStatusBuf, &faceModuleStatus); //更新人脸模组的状态
		dealDataBoxBuf = faceStatusList[NextModeBuf].dealDataBox;
		pFun = Face_Find_Deal_Function(*dealDataBoxBuf, NextStatusBuf); //查找下一模式和下一状态的处理函数
		if (pFun != NULL)
		{
			FACE_TASK_DEBUG_LOG("face task process the pfun");
			pFun(param); //执行处理函数
		}
	}
}

/**
  * @brief  获取人脸模组是否允许打断状态
  *
  * @return ALLOW:允许打断；    
  * 		DISALLOW:不允许打断
  */
static AllowStatus Face_Get_Break_In_Status(void)
{
	return faceModuleStatus.allowBreakIn;
}

/**
  * @brief  获取人脸模组是否忙
  *
  * @return SET:忙   
  * 		RESET:不忙
  */
static FlagStatus Face_Get_Busy_Status(void)
{
	return faceModuleStatus.busy;
}

/**
  * @brief  主控发送给人脸的消息函数
  *
  * @note   
  *
  * @param  
  *
  * @return 
  */
static void Face_Master_To_Face_Msg(Master_Face_Msg_stu_t Msg)
{
	if (rbMasterToFaceMsgHandle == NULL)
	{
		rbMasterToFaceMsgHandle = OSAL_RingBufferCreate(MASTER_TO_FACE_MSG_NUM, sizeof(Master_Face_Msg_stu_t));
	}
	if (rbMasterToFaceMsgHandle != NULL)
	{
		if (ERROR == OSAL_RingBufferWrite(rbMasterToFaceMsgHandle, &Msg))
		{
			FACE_TASK_LOG("write master msg to face ring fail");
		}
		OSAL_EventDelete(COMP_FACE, EVENT_MASTER_TO_FACS_MSG);
		OSAL_EventRepeatCreate(COMP_FACE, EVENT_MASTER_TO_FACS_MSG, 20, EVT_PRIORITY_MEDIUM);
	}
}

static ErrorStatus Face_Ctrl(Master_To_FaceMsg_enum_t msgId, uint8_t param1, uint8_t param2)
{
	FACE_TASK_LOG("Face_Ctrl : %d\r\n", msgId);
	ErrorStatus status = SUCCESS;
	Master_Face_Msg_stu_t msg;

	switch (msgId)
	{
	case MASTER_FACE_SET_ENC_KEY:
		Face_SetTestMode();
	case MASTER_FACE_MSG_OTA:
	case MASTER_FACE_MSG_DEMO:
	case MASTER_FACE_MSG_DISDEMO:
		/* 上电 */
		msg.actionNum = MASTER_FACE_MSG_POWER_ON;
		Face_Master_To_Face_Msg(msg);
		break;
	case MASTER_FACE_MSG_VERITY:
	case MASTER_FACE_MSG_DELETE_VERITY:
		if (FACE_MODULE_VERITYFYING_MODE != Face_Get_FaceModule_CurMode())
		{
			/* 先上电 */
			msg.actionNum = MASTER_FACE_MSG_POWER_ON;
			Face_Master_To_Face_Msg(msg);
		}
		else
		{
			status = ERROR;
		}
		break;
	case MASTER_FACE_MSG_ENROLL:
	case MASTER_FACE_MSG_DELETE:
		/* 终止当前操作 */
		msg.actionNum = MASTER_FACE_MSG_ABORT;
		Face_Master_To_Face_Msg(msg);
		/* 上电 */
		msg.actionNum = MASTER_FACE_MSG_POWER_ON;
		Face_Master_To_Face_Msg(msg);
		break;
	}
	if (status != ERROR)
	{
		if (msgId == MASTER_FACE_MSG_VERITY)
		{
			msg.del_mode = 1;
		}
		else if (msgId == MASTER_FACE_MSG_DELETE_VERITY)
		{
			msg.del_mode = 4;
		}
		msg.actionNum = msgId;
		msg.startNum = param1;
		msg.endNum = param2;
		Face_Master_To_Face_Msg(msg);
	}
	return status;
}

/**
  * @brief  人脸任务给人脸模块上电
  * @note   
  */
static ErrorStatus Face_Power_On(void)
{
	FACE_TASK_LOG("Master ask power on");
	return Face_Ctrl(MASTER_FACE_MSG_POWER_ON, 0, 0);
}

/**
  * @brief  人脸任务结束当前人脸模组的操作（验证、录入）
  * @note   
  */
static ErrorStatus Face_Abort_Current_Operation(void)
{
	FACE_TASK_LOG("Master ask abort");
	return Face_Ctrl(MASTER_FACE_MSG_ABORT, 0, 0);
}

/**
  * @brief  人脸任务 认证人脸
  * @note   
  */
static ErrorStatus Face_Verity_Start(void)
{
	return Face_Ctrl(MASTER_FACE_MSG_VERITY, 0, 0);
}

/**
  * @brief  人脸任务 删除前验证
  * @note   
  */
static ErrorStatus Face_Delete_Verity_Start(void)
{
	return Face_Ctrl(MASTER_FACE_MSG_DELETE_VERITY, 0, 0);
}

/**
  * @brief  人脸任务	录入人脸
  * @note   
  *         
  * @param enroll_num 录入编号
  * @param 
  * 
  */
static ErrorStatus Face_Enroll_Start(uint8_t enrollNum)
{
	Face_Ctrl(MASTER_FACE_MSG_ENROLL, enrollNum, 0);
	return SUCCESS;
}

/**
  * @brief  人脸任务	删除人脸
  * @note   
  *         
  * @param 
  *  
  * @note   endNum  == 0xFF 为删除全部    startNum为起始的删除编号
  * 		endNum ！= 0xFF 为单个删除    startNum ~ endNum 为允许删除的编号范围。
  * 	   
  */
static ErrorStatus Face_Delete_Start(uint8_t startNum, uint8_t endNum)
{
	FACE_TASK_LOG("Master ask start delete(%d, %d)", startNum, endNum);
	/* 直接删除本地索引 */
	if(FACE_DELETE_ALL_NUN == endNum) //删除全部
	{
		Face_DeleteAllIndex();
	}
	else //删除单个
	{
		Face_ReadUserId(startNum, (uint8_t *)&id_to_delete);
		Face_DeleteIndex(startNum);
	}
	return Face_Ctrl(MASTER_FACE_MSG_DELETE, startNum, endNum);
}

/**
  * @brief  人脸任务	设置为演示模式
  * @note   
  *         
  * @param mode:   1: 进入演示模式
  * 			   0: 退出演示模式
  *  
  * @note   
  * 	   
  */
static ErrorStatus Face_Set_Demo_Mode(uint8_t mode)
{
	FACE_TASK_LOG("Master set face demo mode ");
	Master_To_FaceMsg_enum_t msgId = mode ? MASTER_FACE_MSG_DEMO : MASTER_FACE_MSG_DISDEMO;
	return Face_Ctrl(msgId, 0, 0);
}

/**
  * @brief  人脸任务	读取版本号	   
  */
static ErrorStatus Face_Get_Version(Master_Msg_Cb_fun_t cb)
{
	Master_Face_Msg_stu_t Msg;
	Face_Power_On(); //人脸任务给人脸模块上电
	FACE_TASK_LOG("Master ask get version ");

	Msg.actionNum = MASTER_FACE_GET_VERSION;
	Msg.cb = cb;
	Face_Master_To_Face_Msg(Msg);
	return SUCCESS;
}

/**
  * @brief  设定量产加密的秘钥	
  * @note   
  */
static ErrorStatus Face_Set_Enc_Key(void)
{
	FACE_TASK_LOG("Master ask set face enc ");
	Face_Ctrl(MASTER_FACE_SET_ENC_KEY, 0, 0);
	return SUCCESS;
}

/**
  * @brief  人脸恢复出厂设置	
  * @note   
  */
static ErrorStatus Face_Factory(void)
{
	FACE_TASK_LOG("Master ask factory");
	NvFace_stu_t nv_face;
	int len = sizeof(NvFace_stu_t) - sizeof(nv_face.faceReleaseFlag);
	memset(&nv_face.faceSn, 0xff, len);
	OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceSn), &nv_face.faceSn, len);
	return SUCCESS;
}

/**
  * @brief  人脸任务 OTA 启动
  * @note        
  * @param num : 0x00  启动人脸模组算法库升级
  * 			 0x01  启动人脸模组应用层升级
  * @param 
  */
static ErrorStatus Face_OTA_Start(void)
{
	FACE_TASK_LOG("Master ask start face ota");
	Face_Ctrl(MASTER_FACE_MSG_OTA, 0, 0);
	return SUCCESS;
}

/**
  * @brief  人脸模组状态初始化
  * @note
  */
static void Face_FaceModule_Status_Init(void)
{
	FaceBoxData_stu_t *informDataBoxBuf;
	Face_status_enum_t NextStatusBuf = SLEEPED_IDLE_STATUS;	 //下一状态缓存
	Face_mode_enum_t NextModeBuf = FACE_MODULE_SLEEPED_MODE; //下一模式缓存
	informDataBoxBuf = faceStatusList[NextModeBuf].informDataBox;

	Face_Switch_Status(*informDataBoxBuf, NextModeBuf, NextStatusBuf, &faceModuleStatus); //更新人脸模组的状态
}
/**
  * @brief  ota模式，主控消息处理
  *
  * @note   ota模式下，任何主控要求的验证，录入、删除和启动ota指令回复正在ota
  *
  * @param  
  *
  * @return 
  */
static void Face_OTA_Mode_Master_Msg_Process(Master_To_FaceMsg_enum_t actionNum)
{
	switch (actionNum)
	{
	case MASTER_FACE_MSG_VERITY:
	case MASTER_FACE_MSG_DELETE_VERITY:
		Face_SendActionMsg(FACE_ACTION_OTAING, INVALID_NUM);
		Face_SendActionMsg(FACE_ACTION_VERIFY_END, INVALID_NUM);
		break;
	case MASTER_FACE_MSG_ENROLL:
	case MASTER_FACE_MSG_DELETE:
	case MASTER_FACE_MSG_OTA:
		Face_SendActionMsg(FACE_ACTION_OTAING, INVALID_NUM);
		break;

	default:
		break;
	}
}
/**
  * @brief  处理主控发送给人脸的消息
  *
  * @note   
  *
  * @param  
  *
  * @return 
  */
static void Face_Deal_Master_To_Face_Msg(void)
{
	Master_Face_Msg_stu_t masterFaceMsg;
	Face_DealParam_stu_t DealParam = {.pinputdata = NULL};

	/*ota模式下，任何主控要求的验证，录入、删除和启动ota指令回复正在ota*/
	if (FACE_MODULE_OTA_MODE == Face_Get_FaceModule_CurMode()) //正在ota
	{
		if (OSAL_RingBufferRead(rbMasterToFaceMsgHandle, &masterFaceMsg) != SUCCESS) //无消息
			return;
		Face_OTA_Mode_Master_Msg_Process(masterFaceMsg.actionNum);
	}

	if (Face_Get_Break_In_Status() != ALLOW) //当前状态不可打断
		return;

	if (OSAL_RingBufferRead_No_Clear(rbMasterToFaceMsgHandle, &masterFaceMsg) != SUCCESS) //无消息
		return;

	if (Face_Get_Busy_Status() == SET						 //忙状态
		&& masterFaceMsg.actionNum != MASTER_FACE_MSG_ABORT) //不是打断操作
		return;

	if (OSAL_RingBufferRead(rbMasterToFaceMsgHandle, &masterFaceMsg) != SUCCESS) //无消息
		return;

	switch (masterFaceMsg.actionNum)
	{
	case MASTER_FACE_MSG_VERITY: //人脸验证
	case MASTER_FACE_MSG_DELETE_VERITY:
		DealParam.pinputdata = &masterFaceMsg;
		DealParam.event = FACE_MASTER_START_VERITY_EVENT;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	case MASTER_FACE_MSG_ENROLL: //人脸录入
		DealParam.pinputdata = &masterFaceMsg;
		DealParam.event = FACE_MASTER_START_ENROLL_EVENT;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	case MASTER_FACE_MSG_DELETE: //人脸删除
		DealParam.pinputdata = &masterFaceMsg;
		DealParam.event = FACE_MASTER_START_DELETE_EVENT;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	case MASTER_FACE_MSG_ABORT:				//终止当前操作
		DealParam.event = FACE_ABORT_EVENT; //终止当前操作: 终止操作;
		Face_Module_Even_Deal(&DealParam);	//人脸模组事件处理
		break;

	case MASTER_FACE_MSG_POWER_ON:
		DealParam.event = FACE_POWER_ON_EVEN; //上电事件
		Face_Module_Even_Deal(&DealParam);	  //人脸模组事件处理
		break;

	case MASTER_FACE_MSG_OTA: //启动OTA
		DealParam.pinputdata = &masterFaceMsg;
		DealParam.event = FACE_MASTER_START_OTA_EVEN; //启动OTA
		Face_Module_Even_Deal(&DealParam);			  //人脸模组事件处理
		break;

	case MASTER_FACE_MSG_DEMO:					//设置为演示模式
		DealParam.event = FACE_START_SET_EVENT, //人脸设置模式开始
		DealParam.resultId = SET_MSGID_SET_DEMO_MODE;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	case MASTER_FACE_MSG_DISDEMO:				//退出演示模式
		DealParam.event = FACE_START_SET_EVENT, //人脸设置模式开始
		DealParam.resultId = SET_MSGID_SET_WORK_MODE;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	case MASTER_FACE_GET_VERSION:				//获取人脸模组软件版本号
		DealParam.event = FACE_START_SET_EVENT, //人脸设置模式开始
		DealParam.resultId = SET_MSGID_GET_VERSION;
		DealParam.cb = masterFaceMsg.cb;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	case MASTER_FACE_SET_ENC_KEY:				//设定量产加密的秘钥
		DealParam.event = FACE_START_SET_EVENT, //人脸设置模式开始
		DealParam.resultId = SET_MSGID_SET_RELEASE_ENC;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
		break;

	default:
		break;
	}
}

/**
  * @brief  人脸任务循环队列数据处理
  *
  * @note   
  *
  * @param  
  *
  * @return 
  */
static void Face_ProcessorRingBuffData(void)
{
	if (OSAL_RingBufferGetValidSize(rbMasterToFaceMsgHandle) != 0) //扫描主任务发送给人脸的消息
	{
		Face_Deal_Master_To_Face_Msg();
	}

	if (OSAL_RingBufferGetValidSize(rbMasterToFaceMsgHandle) == 0)
	{
		FACE_TASK_LOG("Del  EVENT_MASTER_TO_FACS_MSG");
		OSAL_EventDelete(COMP_FACE, EVENT_MASTER_TO_FACS_MSG);
	}
}

/*****************************人脸模组协议*******************************/

/*功能函数宏定义*/
#define CHECK_SUM_DATA_START 2 //校验和计算起始字节相对帧首字节偏移
#define CHECK_SUN_LEN_ADD 3	   //校验和计算长度相对帧长度增加的个数
///////////// 商汤串口通信协议：数据包结构 /////////////////////////////////////////////////////////////////////////////////////////
#pragma pack(1)
/*帧头数据结构*/
typedef struct
{
	uint16_t stx;  //帧头同步字
	uint8_t msgID; //消息ID
	uint16_t len;  //data数据长度
} ProtocolDataHead_stu_t;

/*加密帧头数据结构*/
typedef struct
{
	uint16_t stx;	//帧头同步字
	uint16_t len;	//data数据长度
	uint8_t data[]; //命令
} ProtocolDataHeadEncrypt_stu_t;

/*帧数据结构*/
typedef struct
{
	ProtocolDataHead_stu_t head; //帧头结构体
	uint8_t data[];				 //命令
} CmdPacket_stu_t;

/*M:模组
 *H:主控*/
/*M->H reply 模块对主控的应答data结构解析 msgID为0x00*/
typedef struct
{
	uint8_t r_msgID;  //应答对应的消息ID和命令的msg_ID 对应
	uint8_t result;	  //应答结果
	uint8_t r_data[]; //应答数据缓存
} Reply_data_stu_t;

/*M->H note 模组主动向主控发送的消息databuf结构解析 msgID为0x01*/
typedef struct
{
	uint8_t n_msgID;  //note ID
	uint8_t n_data[]; //note 数据缓存
} Note_data_stu_t;

/*指令应答等待链表元素数据结构*/
typedef struct
{
	uint8_t msgID;				 //消息id
	uint32_t timeStamp;			 //发送时刻
	uint32_t waitAckTimeout;	 //超时时长
	SensetimeRecvCmdCb_fun_t cb; //应答回调
} WaitAck_stu_t;
#pragma pack()

///////////// 定义协议解析层数据结构 /////////////////////////////////////////////////////////////////////////////////////////
#define PROTOCOL_STX 0xEFAA //帧数据头

#define PROTOCOL_MSGID_REPLY 0x00 //模块对主控发送出的命令的应答
#define PROTOCOL_MSGID_NOTE 0x01  //模块主动发给主控的信息
#define PROTOCOL_MSGID_IMAGE 0x02 //模块给主控传送图片

#define PACK_TYPE_CONFRIM 0X00 //应答包类型：确认包
#define PACK_TYPE_ACK 0X01	   //应答包类型：应答包

#define PROTOCOL_SEND_TIMES 1			//锁发送命令包的最大次数
#define PROTOCOL_RESEND_CMD_TIMEOUT 200 //锁重发命令包间隔时间ms
#define PROTOCOL_WAIT_ACK_TIMEOUT 60000 //锁发出命令包后，等待应答包的时间ms
#define PROTOCOL_SEND_ACK_TIME_GAP 20	//锁发出多包ACK的间隔时间ms

#define PROTOCOL_RX_CMD_BUF_QTY 10				//接收的命令包缓存数量（最多连续接收10个命令包）
#define MAX_PACKAGE_LEN SENSE_TIME_CMD_DATA_LEN //最大包长

/* ���������״̬��Ϣ����¼������Zigbee�����豸�ķ���״̬ */
static struct
{
	uint8_t dataBuf[SENSE_TIME_CMD_OTA_DATA_LEN]; //���ͻ���
	uint8_t dataLen;							  //���ݳ���

	uint8_t cmd;			 //���͵�����
	uint8_t cnt;			 //���ʹ���
	FlagStatus waitAckFlag;	 //�Ƿ�ȴ�ACK��SET���ȴ�ACK����RESET�����ȴ�ACK����
	uint32_t timeStamp;		 //���һ�η��͵�ʱ���
	uint32_t waitAckTimeout; //�ȴ�Ӧ��ʱʱ��
	enum
	{					 //��ǰ���͵�״̬
		TX_STA_IDLE,	 //����
						 //	TX_STA_WAIT_CONFRIM,          //�ȴ�ģ��ظ�ȷ�ϰ�
		TX_STA_WAIT_ACK, //�ȴ�ģ��ظ�Ӧ���
	} status;
} CmdPacketTxInfo;

/* ���������״̬��Ϣ����¼������Zigbee�����豸�ķ���״̬ */
static struct
{
	uint8_t protocolBuf[MAX_PACKAGE_LEN]; //Э���������
	uint8_t protocolCount;				  //Э�������������

	struct
	{
		FlagStatus flag;				 // SET：有数据   RESET：无数据
		uint8_t cmd;					 //�յ�������
		uint8_t param[MAX_PACKAGE_LEN];	 //�յ����������
		uint8_t paramLen;				 //��������
										 //        ZigbeeCmdType_enum_t rxCmdType;  //���յ���������
	} rxBuffer[PROTOCOL_RX_CMD_BUF_QTY]; //��໺��10��rxCmd
	uint8_t index;						 //buf����

	uint16_t cmdTimes; //����ִ�д������յ�������һ��ִ�лص�����������Ϊ0

	uint8_t ackData[MAX_PACKAGE_LEN]; //应答数据包最大的那条为快速读记录  最多读600条记录 一包发过去 +64字节做其他包头包尾用
	uint16_t ackDataLen;			  //应答数据包长度最大的包数据长度超过256
	uint32_t ackSendTimeStamp;		  //���һ�η���Ӧ�����ʱ�䣨�������Ʒ������Ӧ����ļ��ʱ�䣩

	SensetimeRecvCmdCb_fun_t cb; //RX�ص�
} CmdPacketRxInfo;

#define FACEMODULE_TX_CMD_BUFF_NUM 5	   //发送命令环形队列深度
#define FACEMODULE_REG_CALLBACK_BUFF_NUM 1 //应答回调函数环形队列深度
#define FACEMODULE_CONFIG_BUFF_NUM 1	   //人脸配置环形队列深度

static RingBufferHandle_t rbFaceToModuleCmdHandle = NULL; /* 发送循环队列句柄 */

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* ���豸�¼� */
#define EVENT_ZGB_CLOSE ((uint32_t)BIT(1))
/* ��ʱ���豸�¼� */
#define EVENT_ZGB_CLOSE_DELAY ((uint32_t)BIT(2))

/* 回调函数 */
static FaceMessageCallback_fun_t pCmdCallback = NULL;

/**
  * @brief  命令发送回调（发出命令后，无线模块回复的结果）
  * @note
  *
  * @param  type：包类型
  *         PACK_TYPE_CONFRIM：确认包
  *         PACK_TYPE_ACK：应答包
  * @param  cmd：命令
  * @param  pRes：命令发送处理结果
  */
static void Face_SendCmdPacketCallback(uint8_t cmd, uint8_t result, uint8_t *data, uint8_t len)
{
	/* 命令执行结果，回调通知主任务 */
	if (cmd == CmdPacketTxInfo.cmd)
	{
		FACE_TASK_LOG("Send Cmd Callback CMD=%#2X\r\n", cmd);
		if (pCmdCallback != NULL)
		{
			pCmdCallback(result, data, len);
			pCmdCallback = NULL;
		}
		CmdPacketTxInfo.status = TX_STA_IDLE;
	}

	// /* 其他命令执行结果，不用通知主任务 */
	// // ……
}

/**
  * @brief  校验和
  * @note
  *
  * @param  pData为数据指针
  * @param  len数据长度
  * @return 数据异或校验和:
  * 		非加密数据：除帧头（EF AA）和最后一个校验和以外的所有字节都需要计算
  * 		加密数据：除帧头（EF AA）、 长度（从0开始算，第2、3个字节）和最后一个校验和以外的所有字节都需要计算
  */
static uint8_t Face_CalcCheckSum(uint8_t *pData, uint16_t len)
{
	uint8_t sum = 0;
	//FACE_TASK_DEBUG_LOG("check sum:");
	for (; len; len--)
	{
		//FACE_TASK_DEBUG_LOG("%#2x ",*pData);
		sum ^= *pData++;
	}
	//FACE_TASK_DEBUG_LOG("\r\n");
	return sum;
}

/**
  * @brief  获取发送缓存区的状态
  * @note
  *
  * @return 缓存区为空返回0
  */
static uint8_t Face_GetTxBufferStatus(void)
{
	return 0;
}

/**
  * @brief  ��������������ת�����ַ���
  * @note
  * @param  pStr���ַ���������
  * @param  pData��Ҫת��������
  * @param  len�����ݳ���
  *
  * @return ����ת������ַ�������
  */
static void Face_PrintfTxData(uint8_t *pData, uint16_t len)
{
#if defined(DEBUG_EN)
	uint8_t strBuffer[66 * 3], i;
	if (len > 65)
		return; //格式化数组数量不能超过66*3
	for (i = 0; i < len; i++)
	{
		sprintf((char *)&strBuffer[i * 3], "%02X ", pData[i]);
	}
	sprintf((char *)&strBuffer[i * 3], "%s", "\r\n\r\n");
	FACE_TASK_LOG("FaceTask send packet:%s\r\n", strBuffer);
#endif
}

/**
  * @brief  加载待发送的数据
  * @note   将要发出的数据，填入发送缓存区
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus Face_LoadingDataToBeSent(uint8_t *pData, uint16_t len)
{
	if (len > 0x7FFF) //直接发
	{
		len &= 0x7FFF;
		Face_PrintfTxData(pData, len);
		Device_Write(VHW_UART_FACE, pData, len, 0);
		return SUCCESS;
	}
	return ERROR;
}

/**
  * @brief  �ط����������������ʱ�߼�
  *
  * @note   MCU����������󣬳�ʱû���յ�ȷ�ϰ������ط�
  */
static void Face_ResendCmdPacket(void)
{
	//Face_Wiat_Ack_Timeout_Check_Process();
	uint8_t ret = ACK_RES_TIMEOUT;
	uint32_t currentTime = OSAL_GetTickCount();
	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK) //�ȴ�Ӧ���
	{
		if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
		{
			//ERR:超时
			FACE_TASK_LOG("wait ack Time out cmd = %#2x,%#2x,%#2x,%#2x", CmdPacketTxInfo.cmd, currentTime, CmdPacketTxInfo.timeStamp, CmdPacketTxInfo.waitAckTimeout);
			Face_SendCmdPacketCallback(CmdPacketTxInfo.cmd, ret, NULL, 0);

			CmdPacketTxInfo.status = TX_STA_IDLE;
		}
	}
}

/**
  * @brief  �������յ�Ӧ���
  * @note
  *
  * @param  pAckPacket��Ӧ�������ָ��
  */
static void Face_ProcessRxAckPacket(CmdPacket_stu_t *pAckPacket)
{
	Reply_data_stu_t *replyData = (Reply_data_stu_t *)pAckPacket->data;

	Face_SendCmdPacketCallback(replyData->r_msgID, replyData->result, replyData->r_data, pAckPacket->head.len - 2);
}

/**
  * @brief  处理note
  *
  * @note   
  */
static void Face_ProcessSendAckPacket(void)
{
	uint8_t cmd, *pData = NULL, dataLen;

	if (CmdPacketRxInfo.rxBuffer[CmdPacketRxInfo.index].flag == RESET) // 无note数据
	{
		return;
	}
	cmd = CmdPacketRxInfo.rxBuffer[CmdPacketRxInfo.index].cmd;
	pData = CmdPacketRxInfo.rxBuffer[CmdPacketRxInfo.index].param;
	dataLen = CmdPacketRxInfo.rxBuffer[CmdPacketRxInfo.index].paramLen;

	if (CmdPacketRxInfo.cb != NULL)
	{
		CmdPacketRxInfo.cb(cmd, pData, dataLen);
	}
	else
	{
		FACE_TASK_LOG("Unregistered rx callback\r\n");
	}

	CmdPacketRxInfo.rxBuffer[CmdPacketRxInfo.index].flag = RESET;
	CmdPacketRxInfo.index = (CmdPacketRxInfo.index >= PROTOCOL_RX_CMD_BUF_QTY - 1) ? 0 : CmdPacketRxInfo.index + 1;
}

/**
  * @brief  �������յ������
  * @note
  *
  * @param  pCmdPacket�����ݰ�ָ��
  */
static void Face_ProcessRxCmdPacket(CmdPacket_stu_t *pCmdPacket)
{
	uint8_t i, index;
	Note_data_stu_t *noteData = (Note_data_stu_t *)pCmdPacket->data;
	for (i = 0; i < PROTOCOL_RX_CMD_BUF_QTY; i++)
	{
		index = CmdPacketRxInfo.index + i;
		index = (index >= PROTOCOL_RX_CMD_BUF_QTY) ? index - PROTOCOL_RX_CMD_BUF_QTY : index;

		if (CmdPacketRxInfo.rxBuffer[index].flag == RESET)
		{
			CmdPacketRxInfo.rxBuffer[index].flag = SET;
			CmdPacketRxInfo.rxBuffer[index].cmd = noteData->n_msgID;
			CmdPacketRxInfo.rxBuffer[index].paramLen = pCmdPacket->head.len - 1;
			memcpy(CmdPacketRxInfo.rxBuffer[index].param, noteData->n_data, pCmdPacket->head.len - 1);
			break;
		}
	}
}

/**
  * @brief  �������յ����ݰ�
  * @note
  *
  * @param  pData�����ݰ���ַ
  */
static void Face_ParseRxPacket(uint8_t *pData)
{
	CmdPacket_stu_t *pPacketHead = (CmdPacket_stu_t *)pData;
	if (pPacketHead->head.msgID == PROTOCOL_MSGID_REPLY) //处理应答帧(确认包和应答包一起)
	{
		Face_ProcessRxAckPacket((CmdPacket_stu_t *)pData);
	}
	else if (pPacketHead->head.msgID == PROTOCOL_MSGID_NOTE) //模块主动发给主控的信息
	{
		Face_ProcessRxCmdPacket((CmdPacket_stu_t *)pData);
	}
}

/**
  * @brief  从底层环形缓存获取一包数据并解析
  *
  * @note   底层驱动收到数据，会暂存在环形缓存区
  *
  * @return 返回解析后的数据包地址，解析失败返回NULL
  */
static uint8_t *Face_GetOnePacket(void)
{
	static uint8_t getPacketTimeoutCnt = 0;
	uint8_t sum = 0;
	uint16_t packetLen = 0;
	uint8_t tmpData;
	uint32_t tmpLen = 0;
	uint8_t *protocolBuff = NULL, *pCnt = NULL;
	ProtocolDataHead_stu_t *pPacketHead = NULL;
	ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = NULL; //加密模式帧头数据结构

	uint8_t decryptData[MAX_PACKAGE_LEN] = {0};
	uint16_t decryptDataLen;

	tmpLen = OSAL_RingBufferGetValidSize(uartFace_rbHandle);
	if (tmpLen == 0)
	{
		/* 连续3次没有读取到数据（30ms） */
		if (++getPacketTimeoutCnt >= 3)
		{
			if(CmdPacketRxInfo.protocolCount)
			{
				FACE_TASK_LOG("face recv timeout\r\n");
			}
			getPacketTimeoutCnt = 0;
			CmdPacketRxInfo.protocolCount = 0; //清0解析计数
		}
		return NULL;
	}

	getPacketTimeoutCnt = 0;

	pCnt = &(CmdPacketRxInfo.protocolCount);	//解析计数
	protocolBuff = CmdPacketRxInfo.protocolBuf; //解析缓存
	pPacketHead = (ProtocolDataHead_stu_t *)protocolBuff;
	pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)protocolBuff;
	for (; tmpLen; tmpLen--)
	{
		OSAL_RingBufferRead(uartFace_rbHandle, &tmpData); //读取到一个字节数据
		if (*pCnt == 0)
		{
			if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
			{
				// FACE_TASK_LOG("pCnt = 0; %#2x ", tmpData);
				protocolBuff[0] = tmpData;
				*pCnt = 1;
			}
		}
		else if (*pCnt == 1)
		{
			// FACE_TASK_DEBUG_LOG("pCnt = 1; %#2x ", tmpData);
			if (tmpData == (PROTOCOL_STX & 0x00FF)) //帧数据头低字节
			{
				protocolBuff[1] = tmpData;
				*pCnt = 2;
			}
			else if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
			{
				/*再次收到高字节帧头*/
				// protocolBuff[0] = tmpData;
				// *pCnt = 1;
			}
			else
			{
				*pCnt = 0;
			}
		}
		else if (*pCnt > 1) //包头通过后才开始解析数据
		{
			protocolBuff[*pCnt] = tmpData;
			*pCnt = *pCnt + 1;
			if (0 == FaceEncrypt_Get_EnFlag()) //非加密模式
			{
				if (*pCnt == 5)
				{
					pPacketHead->len = SWAP16(pPacketHead->len); //大小端转化
					pPacketHead->stx = SWAP16(pPacketHead->stx); //大小端转化
				}
				if (*pCnt > 5)
				{
					packetLen = pPacketHead->len + 6;
					if (*pCnt >= MAX_PACKAGE_LEN || packetLen == *pCnt)
					{
						if (packetLen == *pCnt)
						{
							sum = Face_CalcCheckSum(protocolBuff + CHECK_SUM_DATA_START, pPacketHead->len + CHECK_SUN_LEN_ADD);
							if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
							{
								FACE_TASK_DEBUG_LOG("RECEIVE RIGHT:");
								for (int i = 0; i < packetLen; i++)
								{
									__FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__FACE_TASK_DEBUG_LOG("\r\n");
								*pCnt = 0;
								return protocolBuff;
							}
							else
							{
								FACE_TASK_DEBUG_LOG("CRC ERR:");
								for (int i = 0; i < packetLen; i++)
								{
									__FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__FACE_TASK_DEBUG_LOG("\r\n");
							}
						}
						*pCnt = 0;
						return NULL;
					}
				}
			}
			else //加密模式
			{
				if (*pCnt == 4)
				{
					pPacketHeadEncrypt->len = SWAP16(pPacketHeadEncrypt->len); //大小端转化
					pPacketHeadEncrypt->stx = SWAP16(pPacketHeadEncrypt->stx); //大小端转化
				}
				if (*pCnt > 4)
				{
					packetLen = pPacketHeadEncrypt->len + 5;
					if (*pCnt >= MAX_PACKAGE_LEN || packetLen == *pCnt)
					{
						if (packetLen == *pCnt)
						{
							sum = Face_CalcCheckSum(pPacketHeadEncrypt->data, pPacketHeadEncrypt->len);
							if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
							{
								FaceEncrypt_SenseTime_Encrypt_Decrypt(0, pPacketHeadEncrypt->data, &pPacketHeadEncrypt->len, decryptData, &decryptDataLen);
								memcpy(&pPacketHeadEncrypt->len, decryptData, decryptDataLen);
								pPacketHead->len = SWAP16(pPacketHead->len); //大小端转化
								FACE_TASK_DEBUG_LOG("RECEIVE RIGHT:");
								for (int i = 0; i < packetLen; i++)
								{
									__FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__FACE_TASK_DEBUG_LOG("\r\n");
								*pCnt = 0;
								if (pPacketHead->len + 6 <= MAX_PACKAGE_LEN)
								{
									return protocolBuff;
								}
								else
								{
									FACE_TASK_DEBUG_LOG("LEN ERR\r\n");
								}
							}
							else
							{
								FACE_TASK_DEBUG_LOG("CRC ERR:");
								for (int i = 0; i < packetLen; i++)
								{
									__FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__FACE_TASK_DEBUG_LOG("\r\n");
							}
						}
						else
						{
							FACE_TASK_DEBUG_LOG("packet err\r\n");
						}
						*pCnt = 0;
						return NULL;
					}
				}
			}
		}
	}
	return NULL;
}

/**
  * @brief  人脸模组协议处理
  *
  * @note   
  */
static void Face_ProtocolProcess(void)
{
	/* 处理人脸模块设备
	 * TXbuf为空，才去解析新数据（如果新解析的数据是一个命令包，就会立即发确认包，要使用TXbuf）
	 * 所以必须等TXbuf的内容发完了，才能去解析新接收的数据
	 */
	uint8_t *pData = NULL;
	pData = (Face_GetTxBufferStatus() == 0) ? Face_GetOnePacket() : NULL; //得到一包数据并检验校验和
	if (pData != NULL)
	{
		err_process(0);
		Face_ParseRxPacket(pData); //解析数据
	}
	Face_ResendCmdPacket();		 //重发命令包
	Face_ProcessSendAckPacket(); //发送ACK包
}

/**
  * @brief  �ж�Э����Ƿ�Ϊ����״̬
  * @note
  *
  * @return ���У�����SUCCESS�� ��æ������ERROR
  */
static ErrorStatus Face_IsProtocolIdle(void)
{

	if (Face_GetTxBufferStatus() == 0 && SLEEPED_IDLE_STATUS != Face_Get_FaceModule_CurStatus() //未上电完成不能发送串口指令
		&& POWERING_ON_STATUS != Face_Get_FaceModule_CurStatus() && CmdPacketTxInfo.status == TX_STA_IDLE)
	{
		return SUCCESS;
	}
	return ERROR;
}

/**
  * @brief  ��������ͽӿ�
  * @note   �����Ҫ���������ݣ����뷢�ͻ�����
  *
  * @param  cmd������������
  * @param  pData������ָ��
  * @param  dataLen�����ݳ���
  * @param  waitAckEnable��1ʹ�ܵȴ�Ӧ�����0���ô���Ӧ���
  */
static void Face_SendCmdPacket(uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag)
{
	CmdPacket_stu_t *pCmdPacket = (CmdPacket_stu_t *)CmdPacketTxInfo.dataBuf;
	ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)CmdPacketTxInfo.dataBuf; //加密模式帧头数据结构
	//uint8_t *check = (uint8_t*)&(pCmdPacket->data[dataLen]);
	uint8_t encryptData[MAX_PACKAGE_LEN] = {0};
	uint16_t encryptDataLen;
	uint16_t encryptInputLen;

	CmdPacketTxInfo.cmd = cmd;
	CmdPacketTxInfo.waitAckFlag = waitAckFlag;
	CmdPacketTxInfo.cnt = 1;
	CmdPacketTxInfo.status = TX_STA_WAIT_ACK;
	CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();

	pCmdPacket->head.stx = PROTOCOL_STX;
	pCmdPacket->head.stx = SWAP16(pCmdPacket->head.stx); //大小端转化
	pCmdPacket->head.msgID = cmd;
	pCmdPacket->head.len = dataLen;						 //data长度
	pCmdPacket->head.len = SWAP16(pCmdPacket->head.len); //大小端转化
	memcpy(pCmdPacket->data, pData, dataLen);

	//if(0 == FaceEncrypt_Get_EnFlag())    //非加密
	{
		pCmdPacket->data[dataLen] = Face_CalcCheckSum((uint8_t *)&(pCmdPacket->head.stx) + CHECK_SUM_DATA_START, dataLen + CHECK_SUN_LEN_ADD);
		CmdPacketTxInfo.dataLen = sizeof(CmdPacket_stu_t) + dataLen + 1;
	}

	if (1 == FaceEncrypt_Get_EnFlag()) //加密模式
	{
		//#if defined (FACE_DEBUG)
		/*打印加密前的串口发送数据*/
		FACE_TASK_LOG("no encrypt packet:");
		Face_PrintfTxData(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen); //仿真模式打印出加密前的数据
																			 //#endif
		pPacketHeadEncrypt->stx = PROTOCOL_STX;
		pPacketHeadEncrypt->stx = SWAP16(pPacketHeadEncrypt->stx); //大小端转化
		encryptInputLen = dataLen + 3;
		FaceEncrypt_SenseTime_Encrypt_Decrypt(1, (uint8_t *)&pCmdPacket->head.msgID, &encryptInputLen, encryptData, &encryptDataLen);

		memcpy(pPacketHeadEncrypt->data, encryptData, encryptDataLen);
		pPacketHeadEncrypt->len = encryptDataLen;

		pPacketHeadEncrypt->data[encryptDataLen] = Face_CalcCheckSum((uint8_t *)pPacketHeadEncrypt->data, encryptDataLen);
		CmdPacketTxInfo.dataLen = sizeof(ProtocolDataHeadEncrypt_stu_t) + encryptDataLen + 1;
		pPacketHeadEncrypt->len = SWAP16(pPacketHeadEncrypt->len); //大小端转化
	}

	Face_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);

	if (cmd == MID_INIT_ENCRYPTION)
	{
		FaceEncrypt_Set_EnFlag(1); //启动加密通信
	}
	else if (cmd == MID_START_OTA)
	{
		FaceEncrypt_Set_EnFlag(0); //关闭加密通信
	}
}

/**
  * @brief  Zigbee���� Э����ʼ��
  *
  * @note
  */
static void Face_ProtocolInit()
{
	__EFRAM static uint8_t init_flag = 0;
	uint8_t faceVersion[FACE_VERSION_LEN+1] = {0};
	uint8_t len = 0;
	CmdPacketTxInfo.status = TX_STA_IDLE;

	CmdPacketRxInfo.index = 0;
	memset(CmdPacketRxInfo.protocolBuf, 0, sizeof(CmdPacketRxInfo.protocolBuf));
	for (uint8_t i = 0; i < PROTOCOL_RX_CMD_BUF_QTY; i++)
	{
		CmdPacketRxInfo.rxBuffer[i].flag = RESET;
	}
	CmdPacketRxInfo.protocolCount = 0;

	Face_FaceModule_Status_Init();

	ErrorStatus ret = Face_Read_Version(faceVersion, &len);
	if (ret == ERROR || init_flag == 0) //首次上电或版本号不存在，获取一次版本号
	{
		init_flag = 1;
		FACE_TASK_LOG("get version");
		Face_Get_Version(NULL);
	}
	else
	{
		FACE_TASK_LOG("face version : %s", faceVersion);
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
  * @brief  人脸模组发送函数 H->M
  * @note   调用此函数时不是立马发送，而是暂存到环形缓存里面
  * @param  pData:发送数据
  */
void Face_Lock_Tx_Face_Cmd(SensetimeTxCmdMsg_stu_t *pData)
{
	if (rbFaceToModuleCmdHandle != NULL)
	{
		OSAL_RingBufferWrite(rbFaceToModuleCmdHandle, pData);
	}
}
/**
  * @brief �������λ����handle
  *
  * @note 
  */
static void Face_CreateRingBuffHandle(void)
{
	static FlagStatus firstPowerOn = SET;
	if (firstPowerOn == SET)
	{
		rbFaceToModuleCmdHandle = OSAL_RingBufferCreate(FACEMODULE_TX_CMD_BUFF_NUM, sizeof(SensetimeTxCmdMsg_stu_t));
		if (rbMasterToFaceMsgHandle == NULL)
		{
			rbMasterToFaceMsgHandle = OSAL_RingBufferCreate(MASTER_TO_FACE_MSG_NUM, sizeof(Master_Face_Msg_stu_t));
		}
		if (uartFace_rbHandle == NULL)
		{
			uartFace_rbHandle = OSAL_RingBufferCreate(500, 1);
		}
		firstPowerOn = RESET;
	}
}

/**
  * @brief  Zigbee���� ע�������¼��Ļص�����
  * @note   ���ô˺���ʱ��һ�������ɹ������������ɹ�ʱ�����ݴ浽���λ�������
  * @param  pFunc:�����¼��Ļص�����
  */
static void Face_RegNoteProcessCallback(SensetimeRecvCmdCb_fun_t pFunc)
{
	CmdPacketRxInfo.cb = pFunc;
	FACE_TASK_LOG("FaceTask Reg Note Callback");
}

static void Face_NoteProcessCallback_Init(SensetimeRecvCmdCb_fun_t pFunc)
{
	static FlagStatus firstPowerOn = SET;
	if (firstPowerOn == SET)
	{
		Face_RegNoteProcessCallback(pFunc);
	}
}

/**
  * @brief  发送指令给人脸模组
  *
  * @note   
  */
static void Face_SendRingBuffNetWorkTxCmd(void)
{
	FlagStatus ackFlag;
	SensetimeTxCmdMsg_stu_t Data = {0};
	OSAL_RingBufferRead_No_Clear(rbFaceToModuleCmdHandle, &Data);
	if ((Face_IsProtocolIdle() == SUCCESS) || (Data.msgID == MID_RESET && FACE_MODULE_SLEEPED_MODE != Face_Get_FaceModule_CurMode())) //在非休眠状态下发重置命令立即执行
	{
		//FACE_TASK_DEBUG_LOG("Face_SendRingBuffNetWorkTxCmd");

		if (OSAL_RingBufferRead(rbFaceToModuleCmdHandle, &Data) == SUCCESS)
		{
			//FACE_TASK_DEBUG_LOG("OSAL_RingBufferRead");
			if (Data.cb != NULL)
			{
				ackFlag = SET;
				pCmdCallback = Data.cb;
				CmdPacketTxInfo.waitAckTimeout = Data.timeout;
				//Face_Wait_Ack_Add(Data.msgID, Data.timeout, Data.cb);
			}
			else
			{
				ackFlag = RESET;
			}
			Face_SendCmdPacket(Data.msgID, Data.dataBuf, Data.data_len, ackFlag);
			FACE_TASK_LOG("RingBuff_Tx_OK msgID = %2x\r\n", Data.msgID);
		}
	}
}

/**
  * @brief 清除人脸发送和设置缓存数据
  *
  * @note  
  */
static void Face_ResetSenseRingBuffData(void)
{
	OSAL_RingBufferReset(rbFaceToModuleCmdHandle);
}

/**
  * @brief 处理人脸发送和设置缓存数据
  *
  * @note  
  */
static void Face_ProcessorSenseRingBuffData(void)
{
	if (OSAL_RingBufferGetValidSize(rbFaceToModuleCmdHandle) != 0)
	{
		Face_SendRingBuffNetWorkTxCmd();
	}
}

/****************************人脸模组end***************************************/
static void Face_TimeoutDeal(void)
{
	uint32_t currentTime = OSAL_GetTickCount();
	Face_DealParam_stu_t DealParam = {
		.pinputdata = NULL,
	};

	if ((faceModuleStatus.timeout != FOREVER_TIME_OUT)											 //非永远不超时
		&& (OSAL_PastTime(currentTime, faceModuleStatus.start_time) > faceModuleStatus.timeout)) //判断是否超时
	{
		DealParam.event = FACE_TIMEOUT_ENENT;
		Face_Module_Even_Deal(&DealParam); //人脸模组事件处理
	}
}

/**
  * @brief 创建周期事件
  * @param 
  * @note  
  */
static void Face_Create_Repeat_Event(void)
{
	/* 创建定时处理人脸协议 */
	OSAL_EventRepeatCreate(COMP_FACE, EVENT_FACE_PROTOCOL, 10, EVT_PRIORITY_MEDIUM);
	/* 创建超时检测协议 */
	OSAL_EventRepeatCreate(COMP_FACE, EVENT_FACE_TIME_OUT, 20, EVT_PRIORITY_MEDIUM);
	/*人脸模组环形消息处理*/
	OSAL_EventRepeatCreate(COMP_FACE, EVENT_FACE_MODULE_MSG, 20, EVT_PRIORITY_MEDIUM);
}
/**
  * @brief 删除周期事件
  * @param 
  * @note  
  */
static void Face_Delete_Event(void)
{
	OSAL_EventDelete(COMP_FACE, EVENT_FACE_PROTOCOL);
	OSAL_EventDelete(COMP_FACE, EVENT_FACE_TIME_OUT);
	OSAL_EventDelete(COMP_FACE, EVENT_FACE_MODULE_MSG);
}

static void Face_ReceiveCb(VirtualHardware_enum_t dev, void *data, uint32_t len)
{
	if (uartFace_rbHandle == NULL)
	{
		return;
	}
	for (uint32_t i = 0; i < len; i++)
	{
		uint8_t tmp = ((uint8_t *)data)[i];
		if (OSAL_RingBufferWrite(uartFace_rbHandle, &tmp) != SUCCESS)
		{
			FACE_TASK_LOG("face ringbuff write err\r\n");
			return;
		}
	}
}

/**
  * @brief  Face_Task任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         3.任务函数必须添加到osal_config.h文件里面
  *
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Face_Task(uint32_t event)
{
	if (event & EVENT_SYS_START) //任务启动
	{
		FACE_TASK_LOG("face task start\r\n");
		/* 打开底层设备 */
		Face_NoteProcessCallback_Init(Sensetime_Process_Note_Msg);
		Face_CreateRingBuffHandle();
		Device_RegisteredCB(VHW_UART_FACE, Face_ReceiveCb);
		Face_Create_Repeat_Event();

		/* 人脸初始化 */
		Face_ProtocolInit();

		/* 注册对外开放的API接口 */
		SYS_API(Face_Power_On);
		SYS_API(Face_Abort_Current_Operation);
		SYS_API(Face_Verity_Start);
		SYS_API(Face_Delete_Verity_Start);
		SYS_API(Face_Enroll_Start);
		SYS_API(Face_Delete_Start);
		SYS_API(Face_Read_Version);
		SYS_API(Face_Read_Model);
		SYS_API(Face_Set_Enc_Key);
		SYS_API(Face_Factory);
		SYS_API(Face_Set_Demo_Mode);
		SYS_API(Face_OTA_Start);
		SYS_API(Face_Get_FaceModule_CurMode);

		return (event ^ EVENT_SYS_START);
	}

	/* 休眠处理 */
	if (event & EVENT_SYS_SLEEP)
	{
		Face_ResetSenseRingBuffData();
		Face_Delete_Event();
		Device_Disable(VHW_UART_FACE);
		FACE_MODULE_POWER_OFF;
		return (event ^ EVENT_SYS_SLEEP);
	}

	/* app to face msg procss */
	if (event & EVENT_MASTER_TO_FACS_MSG)
	{
		Face_ProcessorRingBuffData();
		return (event ^ EVENT_MASTER_TO_FACS_MSG);
	}

	/* face to module msg process */
	if (event & EVENT_FACE_MODULE_MSG)
	{
		Face_ProcessorSenseRingBuffData();
		return (event ^ EVENT_FACE_MODULE_MSG);
	}

	/* 人脸协议处理 */
	if (event & EVENT_FACE_PROTOCOL)
	{
		Face_ProtocolProcess();
		return (event ^ EVENT_FACE_PROTOCOL);
	}

	/* 人脸任务超时事件 */
	if (event & EVENT_FACE_TIME_OUT)
	{
		Face_TimeoutDeal();
		return (event ^ EVENT_FACE_TIME_OUT);
	}

	return 0;
}
COMPONENT_TASK_EXPORT(COMP_FACE, Face_Task, FACE_NV_SIZE);
